Slide 1

Slide 1 text

Lessons Learned Wrapping an Objective-C Framework in Swift NSLondon JP Simard, @simjp, realm.io 1

Slide 2

Slide 2 text

Why? 2

Slide 3

Slide 3 text

Why? API Improvements // Go from this: func objcFunc(a: AnyObject!, b: NSArray!) -> NSString! // to this: func swiftFunc(a: ClassA?, b: [Int]) -> String? // Or using autoclosures, generics, // default parameter values, making types // and optionality explicit, etc. 3

Slide 4

Slide 4 text

Why? To Expose Unmappable Interfaces // Objective-C variable arguments aren't exposed to Swift + (RLMResults *)objectsWhere:(NSString *)format, ...; // neither are #defines #define NSStringFromBool(b) (b ? @"YES" : @"NO") // or certain declarations NSVariableStatusItemLength 4

Slide 5

Slide 5 text

Why Not Rewrite in Swift? 1. Lazy 2. No significant gains from the language 3. Existing codebase complex and/or mature 4. Yup, still lazy 5

Slide 6

Slide 6 text

Step 1: Make dynamic objc framework 6

Slide 7

Slide 7 text

Porting an API RLMObject // ObjC Realm.Object // Swift RLMObject.allObjects() // ObjC objects(type: T.Type) // Swift 7

Slide 8

Slide 8 text

Packaging 1. Dynamic framework, logical 2. Can't statically link Objective-C framework in Swift framework (no modules) 8

Slide 9

Slide 9 text

Exposing Just the Right Interfaces 9

Slide 10

Slide 10 text

Exposing Just the Right Interfaces Making sure Objective-C is still import-able 1. Module Map needs to be preserved 2. Must be a dynamic framework 10

Slide 11

Slide 11 text

Step 2: Setup Swift framework target 11

Slide 12

Slide 12 text

Make Sure Your Framework Compiles ... —when building standalone —when building a target which links against it 12

Slide 13

Slide 13 text

Exposing Just the Right Interfaces Exposing private interfaces just for Swift binding Unfortunately there is no private bridging headers for framework targets 13

Slide 14

Slide 14 text

Exposing Just the Right Interfaces Exposing private interfaces just for Swift binding framework module Realm { umbrella header "Realm.h" export * module * { export * } explicit module Private { header "RLMRealm_Private.h" } } 14

Slide 15

Slide 15 text

Exposing Just the Right Interfaces Don't subclass import Realm class Realm: RLMRealm { // What's wrong with this? } 15

Slide 16

Slide 16 text

Exposing Just the Right Interfaces Don't subclass. Wrap! import Realm class Realm { private var rlmRealm: RLMRealm private init(rlmRealm: RLMRealm) { self.rlmRealm = rlmRealm } } 16

Slide 17

Slide 17 text

Testing 1. Don't test functionality, test interfaces 2. Write equivalency tests 17

Slide 18

Slide 18 text

Documentation 1. Compare Objective-C & Swift interfaces side by side 2. Copy docs from Objective-C 3. Convert doxygen format to ReST 18

Slide 19

Slide 19 text

Publishing —Carthage —CocoaPods 19

Slide 20

Slide 20 text

Links —This talk: github.com/jpsim/talks —Realm: github.com/realm/realm-cocoa —RealmSwift: realm/realm-cocoa/tree/al-swift —jazzy: github.com/realm/jazzy 20

Slide 21

Slide 21 text

Thank You! 21

Slide 22

Slide 22 text

NSLondon().questions?.askThem! JP Simard, @simjp, realm.io 22