Slide 1

Slide 1 text

!!Introspec+ng!Swi0!" dotSwi'(2015,(JP(Simard,(@simjp 1

Slide 2

Slide 2 text

Why? 2

Slide 3

Slide 3 text

Mantle @interface GHIssue : MTLModel @property GHUser *assignee; @property NSDate *updatedAt; @property NSString *title; @property NSString *body; @property NSDate *retrievedAt; @end 3

Slide 4

Slide 4 text

FCModel(&(Realm @interface Employee : RLMObject @property NSString *name; @property NSDate *startDate; @property float salary; @property BOOL fullTime; @end 4

Slide 5

Slide 5 text

How? 5

Slide 6

Slide 6 text

6

Slide 7

Slide 7 text

The$six$ways$to$introspect*Swi- 1. S$ck'with'compile1$me'types'&'constraints 2. Apply'dynamic'cas$ng 3. Leverage'Swi?'s'MirrorType 4. Abuse'Objec$ve1C's'run$me 5. Use'private'func$ons 6. Resort'to'inspec$ng'memory'layout 7

Slide 8

Slide 8 text

The$six$degrees$of$evil 1. S$ck'with'compile1$me'types'&'constraints'–'! 2. Apply'dynamic'cas$ng'–'" 3. Leverage'Swi@'s'MirrorType'–'# 4. Abuse'Objec$ve1C's'run$me'–'$ 5. Use'private'func$ons'–'% 6. Resort'to'inspec$ng'memory'layout'–'& 8

Slide 9

Slide 9 text

Compile()me Types&&&Constraints 9

Slide 10

Slide 10 text

QueryKit struct MyStruct { let intProp: Int struct Attributes { static let intProp = Attribute("intProp") } } // Usage let intProp = MyStruct.Attributes.intProp intProp > 0 // NSPredicate("intProp > 0"), typesafe 10

Slide 11

Slide 11 text

Argo extension User: JSONDecodable { static func create(name: String)(email: String?)(role: Role) (friends: [User]) -> User { return User(name: name, email: email, role: role, friends: friends) } static func decode(j: JSONValue) -> User? { return User.create <^> j <| "name" <*> j <|? "email" // Use ? for parsing optional values <*> j <| "role" // Custom types conforming to JSONDecodable work <*> j <|| "friends" // parse arrays of objects } } 11

Slide 12

Slide 12 text

Dynamic Cas$ng 12

Slide 13

Slide 13 text

as? 13

Slide 14

Slide 14 text

protocol XPCConvertible {} extension Int64: XPCConvertible {} extension String: XPCConvertible {} func toXPC(object: XPCConvertible) -> xpc_object_t? { switch(object) { case let object as Int64: return xpc_int64_create(object) case let object as String: return xpc_string_create(object) default: fatalError("Unsupported type for object: \(object)") return nil } } 14

Slide 15

Slide 15 text

Official Swi$ Reflec%on 15

Slide 16

Slide 16 text

/// The type returned by `reflect(x)`; supplies an API for runtime reflection on `x` protocol MirrorType { /// The instance being reflected var value: Any { get } /// Identical to `value.dynamicType` var valueType: Any.Type { get } /// A unique identifier for `value` if it is a class instance; `nil` otherwise. var objectIdentifier: ObjectIdentifier? { get } /// The count of `value`\ 's logical children var count: Int { get } subscript (i: Int) -> (String, MirrorType) { get } /// A string description of `value`. var summary: String { get } /// A rich representation of `value` for an IDE, or `nil` if none is supplied. var quickLookObject: QuickLookObject? { get } /// How `value` should be presented in an IDE. var disposition: MirrorDisposition { get } } 16

Slide 17

Slide 17 text

struct MyStruct { let stringProp: String let intProp: Int } let reflection = reflect(MyStruct(stringProp: "a", intProp: 1)) for i in 0..

Slide 18

Slide 18 text

Objec&ve(C Run$me 18

Slide 19

Slide 19 text

import Foundation class objcSub: NSObject { let string: String? let int: Int? } var propCount: UInt32 = 0 let properties = clazz_copyPropertyList(objcSub.self, &propCount) for i in 0.. "string" String.fromCString(property_getAttributes(prop))! // => "T@,N,R,Vstring" } 19

Slide 20

Slide 20 text

Using Private Func%ons 20

Slide 21

Slide 21 text

nm -a libswiftCore.dylib | grep "stdlib" > ... > __TFSs28_stdlib_getDemangledTypeNameU__FQ_SS > ... > _swift_stdlib_conformsToProtocol > _swift_stdlib_demangleName > _swift_stdlib_dynamicCastToExistential1 > _swift_stdlib_dynamicCastToExistential1Unconditional > _swift_stdlib_getTypeName > ... 21

Slide 22

Slide 22 text

struct MyStruct { let stringProp: String let intProp: Int } let reflection = reflect(MyStruct(stringProp: "a", intProp: 1)) for i in 0..

Slide 23

Slide 23 text

Inspec'ng Memory Layout 23

Slide 24

Slide 24 text

24

Slide 25

Slide 25 text

25

Slide 26

Slide 26 text

struct _swift_data { unsigned long flags; const char *className; int fieldcount, flags2; const char *ivarNames; struct _swift_field **(*get_field_data)(); }; struct _swift_class { union { Class meta; unsigned long flags; }; Class supr; void *buckets, *vtable, *pdata; int f1, f2; // added for Beta5 int size, tos, mdsize, eight; struct _swift_data *swiftData; IMP dispatch[1]; }; 26

Slide 27

Slide 27 text

class GenericClass {} class SimpleClass: NSObject {} class ParentClass { let boolProp: Bool? // Optionals let intProp: Int // Without default value var floatProp = 0 as Float // With default value var doubleProp = 0.0 var stringProp = "" var simpleProp = SimpleClass() var genericProp = GenericClass() } 27

Slide 28

Slide 28 text

{ "boolProp": "b", "intProp": "i", "floatProp": "f", "doubleProp": "d", "stringProp": "S", "simpleProp": "ModuleName.SimpleClass", "genericProp": "[Mangled GenericClass]" } 28

Slide 29

Slide 29 text

Why? 29

Slide 30

Slide 30 text

RealmSwi) class Employee: Object { dynamic var name = "" // you can specify defaults dynamic var startDate = NSDate() dynamic var salary = 0.0 dynamic var fullTime = true } class Company: Object { dynamic var name = "" dynamic var ceo: Employee? // optional let employees = List() } 30

Slide 31

Slide 31 text

The$six$ways$to$introspect*Swi- 1. S$ck'with'compile1$me'types'&'constraints'–'! 2. Apply'dynamic'cas$ng'–'" 3. Leverage'Swi@'s'MirrorType'–'# 4. Abuse'Objec$ve1C's'run$me'–'$ 5. Use'private'func$ons'–'% 6. Resort'to'inspec$ng'memory'layout'–'& 31

Slide 32

Slide 32 text

Links&(1/2) • This&talk:&github.com/jpsim/talks • Mantle:&github.com/Mantle/Mantle • FCModel:&github.com/marcoarment/FCModel • Realm:&github.com/realm/realm9cocoa • QueryKit:&github.com/QueryKit/QueryKit • Argo:&github.com/thoughtbot/Argo 32

Slide 33

Slide 33 text

Links&(2/2) • Dynamic)Cas,ng:)blog.segiddins.me • Swi1XPC:)github.com/jpsim/Swi5XPC • MirrorType)Docs:)swi5doc.org/protocol/MirrorType • Russ)Bishop)on)horrible)things:)russbishop.net • Injec,on)for)Xcode:)injec=onforxcode.com • Swi1IvarTypeDetector:)github.com/jpsim/Swi5IvarTypeDetector 33

Slide 34

Slide 34 text

Thank&You! 34

Slide 35

Slide 35 text

dotSwift().questions?.askThem! JP#Simard,#@simjp,#realm.io 35