swift funtime
DESCRIPTION
An exploration of the new (?) runtime and how the Objective-C runtime API can be used in Swift. Talk given at mobiconf 2014.TRANSCRIPT
![Page 1: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/1.jpg)
SWIFT FUNTIMEMOBICONF 2014
BORIS BÜGLING - @NEONACHO
![Page 2: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/2.jpg)
COCOAPODS
![Page 3: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/3.jpg)
CONTENTFUL
![Page 4: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/4.jpg)
SWIFT
![Page 5: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/5.jpg)
AGENDA▸ How do you even Swift?▸ What is a Swift object?
▸ Objective-C runtime in the age of Swift▸ Swift runtime▸ (some Q&A)
![Page 6: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/6.jpg)
“Swift’s clean slate [...] is an opportunity to reimagine how software
development works.”
![Page 7: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/7.jpg)
▸ Optionals▸ Tuples▸ Generics
▸ Pattern matching▸ Operator overloading▸ Namespaces▸ Type inference
▸ ...
![Page 8: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/8.jpg)
EMOJI IDENTIFIERS! !class ! { func "() { }}
![Page 9: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/9.jpg)
INTERFACES WITH C, AT FULL
SPEEDWATCH "SWIFT AND C" BY
MIKE ASH
![Page 10: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/10.jpg)
DROPS C++ INTEROPERABILITY
![Page 11: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/11.jpg)
Everyone is a Beginner
![Page 12: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/12.jpg)
▸ The Swift Programming Language by
AND ALSO
▸ Swift by Tutorials: A Hands-On Approach▸ Your First Swift App
▸ Functional Programming in Swift
![Page 13: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/13.jpg)
SWIFT COMMAND LINE TOOLS$ xcrun swiftWelcome to Swift! Type :help for assistance.
$ xcrun swiftc Foo.swift## will compile an executable
$ xcrun swift-stdlib-tool## assembles libraries for an application bundle
$ xcrun swift-demangle _TtCSs29_NativeDictionaryStorageOwner_TtCSs29_NativeDictionaryStorageOwner ---> Swift._NativeDictionaryStorageOwner
![Page 14: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/14.jpg)
LET'S DROP CLOSE TO THE METAL
![Page 15: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/15.jpg)
WHAT IS A SWIFT OBJECT?
![Page 16: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/16.jpg)
IT DEPENDS
![Page 17: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/17.jpg)
class MyObject : NSObject {}
![Page 18: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/18.jpg)
▸ behaves like any old Objective-C object▸ instance variables are properties▸ fully interopable with ObjC
![Page 19: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/19.jpg)
class MyObject {}
![Page 20: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/20.jpg)
▸ has SwiftObject as superclass▸ instance variables are ivars▸ ivars have no type encoding▸ methods are not ObjC methods▸ not interoperable with ObjC
![Page 21: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/21.jpg)
PLAYGROUND!
import ObjectiveC.runtime
butPlayground execution failed: Error in auto-import:failed to get module 'runtime' from AST context
(rdar://problem/18482380)
![Page 22: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/22.jpg)
!"
![Page 23: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/23.jpg)
DEMO: INSPECT OBJECTS
![Page 24: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/24.jpg)
SWIFTOBJECT
Ivar: magic {SwiftObject_s="isa"^v"refCount"q}Protocol: NSObject
NSOBJECT
Ivar: isa #Protocol: NSObject
![Page 25: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/25.jpg)
class MySwiftClass { var foo = "bar";
init() { }}
import Foundationimport ObjectiveC.runtime
var ivar = class_getInstanceVariable(MySwiftClass().dynamicType, "foo")var value : AnyObject = object_getIvar(MySwiftClass(), ivar)!
Segmentation fault: 11
![Page 26: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/26.jpg)
#import <Foundation/Foundation.h>#import <objc/runtime.h>
@interface MyClass : NSObject
@property (nonatomic, retain) NSString* foo;
@end
#pragma mark -
@implementation MyClass
-(instancetype)init { self = [super init]; if (self) { self.foo = @"bar"; } return self;}
@end
#pragma mark -
int main(int argc, char *argv[]){ @autoreleasepool { MyClass* object = [MyClass new]; Ivar ivar = class_getInstanceVariable(object.class, "_foo"); id value = object_getIvar(object, ivar); NSLog(@"%@", value); return 0; }}
![Page 27: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/27.jpg)
VALUE TYPES SHOULD BE STRUCTSstruct MyObject { var a : String var b : Array<Int>}
![Page 28: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/28.jpg)
IN PURE SWIFT, THERE'S NO INTROSPECTION !
![Page 29: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/29.jpg)
THERE IS HOPE/// How children of this value should be presented in the IDE.enum MirrorDisposition { case Struct case Class case Enum case Tuple [...]}
/// A protocol that provides a reflection interface to an underlying value.protocol MirrorType { [...]
/// Get the number of logical children this value has. var count: Int { get } subscript (i: Int) -> (String, MirrorType) { get }
/// Get a string description of this value. var summary: String { get }
[...]}
![Page 30: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/30.jpg)
// From: https://gist.github.com/peebsjs/9288f79322ed3119ece4
infix operator --> {}func --> (instance: Any, key: String) -> Any? { let mirror = reflect(instance)
for index in 0 ..< mirror.count { let (childKey, childMirror) = mirror[index] if childKey == key { return childMirror.value } }
return nil}
//Examplestruct MyPoint { let x: Float let y: Float}
let point = MyPoint(x: 1, y: 2)println(point --> "x")println(point --> "y")
![Page 31: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/31.jpg)
OBJECTIVE-C RUNTIME IN THE
AGE OF SWIFT
![Page 32: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/32.jpg)
INHERIT FROM NSObject AND IT JUST WORKS!
![Page 33: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/33.jpg)
EVEN SWIZZLING !
![Page 34: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/34.jpg)
import Foundationimport ObjectiveC.runtime
extension NSString { func swizzle_description() -> NSString { return "!" }}
var myString = "foobar" as NSString
println(myString.description)
var originalMethod = class_getInstanceMethod(NSString.self, "description")var swizzledMethod = class_getInstanceMethod(NSString.self, "swizzle_description")
method_exchangeImplementations(originalMethod, swizzledMethod)
println(myString.description)
![Page 35: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/35.jpg)
![Page 36: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/36.jpg)
![Page 37: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/37.jpg)
OR REPLACING METHODSimport Foundationimport ObjectiveC.runtime
let myString = "foobar" as NSString
println(myString.description)
let myBlock : @objc_block (AnyObject!) -> String = { (sself : AnyObject!) -> (String) in "✋"}
let myIMP = imp_implementationWithBlock(unsafeBitCast(myBlock, AnyObject.self))let method = class_getInstanceMethod(myString.dynamicType, "description")method_setImplementation(method, myIMP)
println(myString.description)
![Page 38: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/38.jpg)
LET'S TAKE A STEP BACK
![Page 39: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/39.jpg)
OBJECTStypedef struct objc_object { Class isa;} *id;
![Page 40: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/40.jpg)
CLASSESstruct objc_class { Class isa;
#if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; const char *name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; struct objc_method_list **methodLists OBJC2_UNAVAILABLE; struct objc_cache *cache OBJC2_UNAVAILABLE; struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;#endif} OBJC2_UNAVAILABLE;
![Page 41: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/41.jpg)
OBJECTS
▸ struct magic▸ contains refCount and isa
▸ methods are in virtual table, like in C++
CLASSES▸ have mangled names, which contain the module name
![Page 42: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/42.jpg)
NAME MANGLINGanother C++ concept
_TFV4test1eCfMS0_FT_S0_ ---> test.e.init (test.e.Type)() -> test.e_TMLCCC4test1a1b1c ---> lazy cache variable for type metadata for test.a.b.c_TMmCCC4test1a1b1c ---> metaclass for test.a.b.c_TMnCC4test1a1b ---> nominal type descriptor for test.a.b
_TTWOV4test1e1fSs9EquatableFS2_oi2eeUS2___fMQPS2_FTS3_S3__Sb ---> protocol witness for Swift.Equatable.== infix <A : Swift.Equatable>(Swift.Equatable.Self.Type)(Swift.Equatable.Self, Swift.Equatable.Self) -> Swift.Bool in conformance test.e.f : Swift.Equatable
_TWoFC4test1aCfMS0_FT_S0_ ---> witness table offset for test.a.__allocating_init (test.a.Type)() -> test.a
_TWoFCCC4test1a1b1c1dfS2_FT1zS0_1xS1_1vFT1xSi_Si_OVS_1e1f ---> witness table offset for test.a.b.c.d (test.a.b.c)(z : test.a, x : test.a.b, v : (x : Swift.Int) -> Swift.Int) -> test.e.f
![Page 43: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/43.jpg)
HOW ARE EMOJI FORMED?$ echo 'class ! {}'|xcrun swiftc -emit-library -o test -$ nm -g test...0000000000000db0 T __TFC4testX4ypIhD...$ xcrun swift-demangle __TFC4testX4ypIhD_TFC4testX4ypIhD ---> test.!.__deallocating_deinit
X4 ypIh ~ xn--yp8h
![Page 44: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/44.jpg)
METHODSstruct objc_method { SEL method_name OBJC2_UNAVAILABLE; char *method_types OBJC2_UNAVAILABLE; IMP method_imp OBJC2_UNAVAILABLE;} OBJC2_UNAVAILABLE;
![Page 45: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/45.jpg)
METHOD IMPLEMENTATIONStypedef struct objc_selector *SEL;
typedef id (*IMP)(id self, SEL _cmd ,...);
![Page 46: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/46.jpg)
MESSAGE FORWARDING+(BOOL)resolveInstanceMethod:(SEL)aSEL;
-(void)forwardInvocation:(NSInvocation*)anInvocation;
-(NSMethodSignature*)methodSignatureForSelector:(SEL)selector;
-(BOOL)respondsToSelector:(SEL)aSelector;
![Page 47: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/47.jpg)
FROM UIVIEWCONTROLLER.H- (void)attentionClassDumpUser:(id)arg1 yesItsUsAgain:(id)arg2 althoughSwizzlingAndOverridingPrivateMethodsIsFun:(id)arg3 itWasntMuchFunWhenYourAppStoppedWorking:(id)arg4 pleaseRefrainFromDoingSoInTheFutureOkayThanksBye:(id)arg5;
![Page 48: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/48.jpg)
CHANGE CLASSES AT RUNTIME▸ method_setImplementation()▸ class_addMethod()
▸ ...
![Page 49: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/49.jpg)
DEMO: DYNAMIC TABLE VIEW
![Page 50: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/50.jpg)
NSINVOCATION DOES NOT EXIST
![Page 51: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/51.jpg)
BUT WHAT CAN WE DO ABOUT PURE SWIFT?
![Page 52: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/52.jpg)
SWROUTE▸ PoC of function hooking in Swift
▸ Uses rd_route, a Mach specific injection library for C
![Page 53: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/53.jpg)
#include <stdint.h>
#define kObjectFieldOffset sizeof(uintptr_t)
struct swift_func_object { uintptr_t *original_type_ptr;#if defined(__x86_64__) uintptr_t *unknown0;#else uintptr_t *unknown0, *unknown1;#endif uintptr_t function_address; uintptr_t *self;};
uintptr_t _rd_get_func_impl(void *func) { struct swift_func_object *obj = (struct swift_func_object *)*(uintptr_t *)(func + kObjectFieldOffset);
return obj->function_address;}
![Page 54: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/54.jpg)
SWIFT RUNTIME
![Page 55: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/55.jpg)
▸ libswiftCore.dylib
implementations of NSSwiftArray, etc.▸ libswiftRuntime.a
low-level primitives like swift_release
![Page 56: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/56.jpg)
HOPPER
![Page 57: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/57.jpg)
COMPATIBILITY
▸ App Compatibility ✅▸ Binary Compatibility ⛔️▸ Source Compatibility ⛔️
![Page 58: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/58.jpg)
Foo.app boris$ find . -type f./Frameworks/libswiftCore.dylib./Frameworks/libswiftCoreGraphics.dylib./Frameworks/libswiftCoreImage.dylib./Frameworks/libswiftDarwin.dylib./Frameworks/libswiftDispatch.dylib./Frameworks/libswiftFoundation.dylib./Frameworks/libswiftObjectiveC.dylib./Frameworks/libswiftUIKit.dylib./Info.plist./PkgInfo./Foo
![Page 59: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/59.jpg)
TWO FINAL TIDBITS
![Page 60: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/60.jpg)
SPEED▸ less dynamic dispatch
▸ omits _cmd - freeing one register▸ usually no pointer aliasing
int *ptrA = malloc(100 * sizeof(*ptrA));int *ptrB = ptrA;
![Page 61: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/61.jpg)
class BankAccount { var balance: Double = 0.0
func deposit(amount: Double) { balance += amount }}
let account = BankAccount()account.deposit(100)
let depositor = BankAccount.depositdepositor(account)(100)
BankAccount.deposit(account)(100)
![Page 62: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/62.jpg)
METHODS ARE CURRIED FUNCTIONS
![Page 63: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/63.jpg)
![Page 64: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/64.jpg)
YOU DON'T NEED OBJECTIVE-C
ANYMORE
![Page 65: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/65.jpg)
UNLESS YOU BUILD FRAMEWORKS OR NEED TO
WORK WITH C++
![Page 66: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/66.jpg)
BUT THE OBJC RUNTIME IS STILL STRONG
![Page 67: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/67.jpg)
THANK YOU!
![Page 68: Swift funtime](https://reader031.vdocuments.net/reader031/viewer/2022020920/55932e691a28ab72548b456b/html5/thumbnails/68.jpg)
▸ https://www.mikeash.com/pyblog/▸ http://airspeedvelocity.net/
▸ https://developer.apple.com/swift/blog/▸ http://www.russbishop.net/swift-how-did-i-do-horrible-things