What's simctl command-line tool, how to achieve great user experience with method swizzling and build dynamic libraries for iOS as a plugin.
Where could you apply knowledge of writing own iOS Simulator plugins and how this will make you a better developer.
Delivered on Cocoaheads Kyiv #15.
7. @ahmed_sulajman
SIMULATOR INTRO New in Simulator since Xcode 9
Launch multiple
iOS Simulator
Resize iOS Simulator
like regular window
Full-Screen mode
along with Xcode
8. @ahmed_sulajman
SIMULATOR INTRO Why Simulator is important
30%
30%
30%
10%
!
"
# Testing in iOS Simulator
during development
Actual Development
Communication
Meetings
Compiling & Building…
9. @ahmed_sulajman
AGENDA
Intro to simctl
What is simctl and what it allows you to do now
!
Method Swizzling
How you can change implementation of the method you have no access to
"
Building Dynamic Library
How to make a dynamic library for iOS and how to upload it to iOS Simulator
#
What’s next for iOS Simulator plugins
Where to go from here and how you can enhance iOS Simulator plugins even more
$
simctl
14. @ahmed_sulajman
SIMCTL What simctl can do devices list
> xcrun simctl list -j [devices|devicetypes|runtimes|pairs]
List available devices, device types, runtimes, or device pairs
15. @ahmed_sulajman
SIMCTL
> xcrun simctl list -j [devices|devicetypes|runtimes|pairs]
> xcrun simctl list -j devices $someSearchTerm
What simctl can do devices list
16. @ahmed_sulajman
SIMCTL
> xcrun simctl list -j [devices|devicetypes|runtimes|pairs]
{
"devices" : {
"com.apple.CoreSimulator.SimRuntime.iOS-12-2" : [
{
"availability" : "(available)",
"state" : "Shutdown",
"isAvailable" : true,
"name" : "iPad Air (3rd generation)",
"udid" : "18D30337-C8E3-43AE-8765-5D935D9408BF",
"availabilityError" : ""
}
]
}
}
What simctl can do devices list
17. @ahmed_sulajman
SIMCTL
> xcrun simctl boot <device>
Boot a specific device
> xcrun simctl shutdown <device> | all
Shutdown a specific device or all devices
What simctl can do boot & shutdown device
18. @ahmed_sulajman
SIMCTL
> xcrun simctl io booted recordVideo --type=mp4 <file path>
Records the display to the specified file or url (use "-" for stdout).
What simctl can do video recording
20. @ahmed_sulajman
SIMCTL
> xcrun simctl spawn
syslog
leaks
malloc_history
...
heap
notifyutil
logstringdups
iOS Simulator
Tools and utils in iOS Runtime
macOS Environment
Launching process from macOS inside Simulator
spawn
What simctl can do spawn process
21. @ahmed_sulajman
SIMCTL
> xcrun simctl spawn
Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/
Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/
Resources/RuntimeRoot/usr/...
Collect system log into a log archive, watch live system logs
log!
Search through a process for leaked memory
leaks!
Displays/aggregates allocation histories in a process
malloc_history!
What simctl can do spawn process
25. @ahmed_sulajman
SIMCTL Conclusions
simctl is the main interface to iOS Simulatorsimctl
via simctl interact with Simulator and explore its process as it isn’t an Emulator
!
spawn tool allows you to launch internal toolsspawn
By typing exact executable you can spawn a process in iOS Simulator
!
Using launchctl allows you to manage serviceslaunchctl
spawn allows you to launch internal tools inside iOS Simulator
!
28. @ahmed_sulajman
SWIZZLING How does it work
Objective-C Runtime
The Objective-C runtime is a runtime library that provides support
for the dynamic properties of the Objective-C language, and as such
is linked to by all Objective-C apps
#import <objc/runtime.h>
30. @ahmed_sulajman
SWIZZLING How does it work class dispatch table
Dispatch TableObjetive-C Class
Method Selector Implementation
Method Selector Implementation
Method Selector Implementation
31. @ahmed_sulajman
SWIZZLING How does it work class dispatch table
@interface HelloRuntime: NSObject
- (void)hello:(NSString *)text;
@end
@implementation HelloRuntime
- (void)hello:(NSString *)text {
NSLog(@"Hello, %@!", text);
}
@end
32. @ahmed_sulajman
SWIZZLING How does it work
Method: -[hello:] Selector: @selector(hello:)
class dispatch table
NSLog(@"Hello, %@!", text);
Implementation
33. @ahmed_sulajman
SWIZZLING How does it work replace method implementation
NSLog(@"Hello, %@!", text);
ImplementationAlt Implementation
Method: -[hello:]
Method: -[alt_hello:]
Selector: @selector(hello:)
Selector: @selector(alt_hello:)
34. @ahmed_sulajman
SWIZZLING How does it work replace method implementation
Alt Implementation
NSLog(@"Hello, %@!", text);
Implementation
Method: -[hello:]
Method: -[alt_hello:]
Selector: @selector(hello:)
Selector: @selector(alt_hello:)
35. @ahmed_sulajman
- (void)alt_hello:(NSString *)text {
[self alt_hello:@"Cocoaheads Kyiv"];
// DO not call original -[hello:] here
// it will lead to infinite loop
// [self hello:@"Cocoaheads Kyiv"];
}
SWIZZLING How does it work replace method implementation
37. @ahmed_sulajman
SWIZZLING How to implement it
How-to Swizzle
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
});
}
38. @ahmed_sulajman
SWIZZLING How to implement it
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(hello:);
SEL swizzledSelector = @selector(alt_hello:);
Method originalMethod = class_getInstanceMethod(class, originalSeletor);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
});
}
How-to Swizzle
39. @ahmed_sulajman
SWIZZLING How to implement it
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(hello:);
SEL swizzledSelector = @selector(alt_hello:);
Method originalMethod = class_getInstanceMethod(class, originalSeletor);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
});
}
How-to Swizzle
method_exchangeImplementations( )
Use method_exchangeImplementations( ) with cautions. Better
explore class_addMethod( ) and class_replaceMethod( )
⚠
40. @ahmed_sulajman
SWIZZLING Conclusions
Every class has dispatch table
It allows the class to understand which selector corresponds to which method
!
Change dispatch table in runtime
Objective-C Runtime allow us to change dispatch table and assign different IMP to SEL
!
Pay a!ention when doing swizzling
Use +[load] and dispatch_once to ensure your code runs once when the class has been loaded
!
43. @ahmed_sulajman
DYLIB What is dynamic library Static vs Dynamic
App with Dynamic LibrariesApp with Static Libraries
VS
Source Code
Static Libs
Source Code
Dynamic Libs
References
44. @ahmed_sulajman
DYLIB What is dynamic library How does it work
DYLD_LIBRARY_PATH
Specify primary directories where in file system dynamic loader
needs to search for dynamic libraries.
DYLD_FALLBACK_LIBRARY_PATH
Specify secondary directories where in file system dynamic loader
needs to search for dynamic libraries before searching in system
directories in case there was nothing found in primary directories.
DYLD_INSERT_LIBRARIES
Specify dynamic libraries which needs to be loaded before primary
libraries.
45. @ahmed_sulajman
DYLIB What is dynamic library How does it work
DYLD_LIBRARY_PATH
Specify primary directories where in file system dynamic loader
needs to search for dynamic libraries.
DYLD_FALLBACK_LIBRARY_PATH
Specify secondary directories where in file system dynamic loader
needs to search for dynamic libraries before searching in system
directories in case there was nothing found in primary directories.
DYLD_INSERT_LIBRARIES
Specify dynamic libraries which needs to be loaded before primary
libraries.
47. @ahmed_sulajman
What’s next for iOS Simulator plugins
Where to go from here and how you can enhance iOS Simulator plugins even more
!
48. @ahmed_sulajman
NEXT STEPS What might be improved
Add communication channel
Launch simple server in iOS Simulator plugin to send requests and handle them
!
49. @ahmed_sulajman
NEXT STEPS What might be improved
Add communication channel
Launch simple server in iOS Simulator plugin to send requests and handle them
!
Swizzle public and private methods
BY using objc_getClass("ClassName") you can get access to privat classes
and get its instance. Explore class-dump to get privat methods
!
50. @ahmed_sulajman
NEXT STEPS Real use-cases
Add communication channel
Launch simple server in iOS Simulator plugin to send requests and handle them
"
Swizzle public and private methods
BY using objc_getClass("ClassName") you can get access to privat classes
and get its instance. Explore class-dump to get privat methods
"
Capture screenshot with context
Intercept screenshot capture event to put additional information for debugging purpose
!
51. @ahmed_sulajman
NEXT STEPS Real use-cases
Add communication channel
Launch simple server in iOS Simulator plugin to send requests and handle them
"
Swizzle public and private methods
BY using objc_getClass("ClassName") you can get access to privat classes
and get its instance. Explore class-dump to get privat methods
"
Live UI editing
Select UI components in running application and change their style in the runtime
!
Capture screenshot with context
Intercept screenshot capture event to put additional information for debugging purpose
!
52. @ahmed_sulajman
Conclusions
simctl is a powerfull iOS Simulator tool
simctl by itself opens a range of possibnoities for interacting with iOS Simulator
☝
Method Swizzling
Using Objective-C runtime you can change implementation of methods you have to access to
☝
Dynamic Libraries as plugins for iOS Simulator
Build and upload dynamic libraries into iOS Simulator to enhamce its functionaly
☝