Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Let's migrate to 3.0

Let's migrate to 3.0

Xcode 8.0 and SDK 10 bring swift 3.0 with it! You certainly didn't have the opportunity to start a brand new project on it yet, so let's talk about the migration, it's steps and the issues encountered.

David Bonnet

January 19, 2017
Tweet

More Decks by David Bonnet

Other Decks in Programming

Transcript

  1. A LITTLE BIT OF HISTORY… ▸ From Swift 1.x to

    Swift 2.x ▸ Just remember ErrorType and throwable types ▸ Swift 3.0 is the first community version ! " ‣ it also breaks code !
  2. LET’S DO IT SOFTLY - SWIFT 2.3 A LIGHTWEIGHT UPDATE

    ▸ Only takes advantage of Nullability Checking on Objective-C Interoperability // Swift 2.2 let image = CIImage(MTLTexture: texture, options: options) let extent = image.extent // this code can lead to a crash // Swift 3.0 if let image = CIImage(MTLTexture: texture, options: options) { … } ▸ This can help you migrate quickly to the SDK 10 on a big base code % 5
  3. LET’S DO IT SOFTLY - SWIFT 2.3 A TEMPORARY SOLUTION

    ▸ Xcode loses code sense (even more than usual) ▸ Sometimes completion code is absent / No code coloration when lost ▸ When showing real-time errors in source code, Xcode can get lost ▸ this is valid swift 2.3 code ! and it builds ▸ fixed in latest Xcode 8.2.1 ▸ Xcode 8.2.x is the last version to support it! 6
  4. LET’S MIGRATE - SWIFT 3.0 1. MIGRATE YOUR DEPENDENCIES -

    COCOAPODS / CARTHAGE ▸ Long live Objective-C! ▸ Almost nothing to do here… ▸ Some authors have annotated their libraries: better swift interoperability! ▸ Others have created a brand new swift version: ▸ MMDrawerController has been converted to DrawerController drawerController?.openDrawerGestureModeMask = MMOpenDrawerGestureMode.None [X] ’None' has been renamed to 'none' 12 https://github.com/mutualmobile/MMDrawerController/issues/476 drawerController?.openDrawerGestureModeMask = MMOpenDrawerGestureMode.none [X] 'none' is unavailable: use [] to construct an empty option set
  5. LET’S MIGRATE - SWIFT 3.0 1. MIGRATE YOUR DEPENDENCIES -

    COCOAPODS / CARTHAGE ▸ ⚠ update your libraries means update also their APIs or introduce new features! extension Results { func toArray() -> [T] { return self.map {$0} } } extension RealmSwift.List { func toArray() -> [T] { return self.map {$0} } } 13 => //New definition in RxRealm extension List: NotificationEmitter { public typealias ElementType = Element public func toArray() -> [Element] { return Array(self) } }
  6. 14 ▸ Migrate your code template before the migration! ▸

    SwiftGen - https://github.com/AliSoftware/SwiftGen -t swift3 LET’S MIGRATE - SWIFT 3.0 2. USING A CODE GENERATOR? #!/bin/sh swiftgen strings
  7. 15 ▸ Use a linter? Disable it during the migration.

    ▸ SwiftLint - https://github.com/realm/SwiftLint 1. Launch the migration assistant on your targets only 2. Analyse each source file: 1. Fix it if needed 2. Uncheck from migration when it’s a third party file 3. Do not hesitate to pass the migrator several times LET’S MIGRATE - SWIFT 3.0 3. SOME OTHER THINGS
  8. 17 ▸ To avoid renaming all your APIs calls: ▸

    _ is automatically added, you probably want to name them properly func updateIdentityWithName(_ name: String, firstname: String) throws ▸ Some Foundation objects with deleted NS prefix are casted to conform to new APIs let url = NSURL(string: "http://someurl.com" ) URLComponents(url: url as URL, resolvingAgainstBaseURL: false) REAL WORLD PROBLEMS BEWARE SOME CHANGES ARE MADE AUTOMATICALLY SE-0046 if let url = URL(string: "http://someurl.com" ) { URLComponents(url: url, resolvingAgainstBaseURL: false) } func updateIdentity(name: String, firstname: String) throws
  9. 18 ▸ A cast to AnyObject is frequently added although

    new APIs accept Any ▸ Convert your JSON objects to [String: Any] ▸ ⚠ Some types becomes values types! ▸ public struct Date versus open class NSDate ▸ But it can simplify the reading: ▸ (x as NSDate).earlierDate(y) can be changed to x < y ? x : y REAL WORLD PROBLEMS BEWARE SOME CHANGES ARE MADE AUTOMATICALLY https://developer.apple.com/swift/blog/?id=39
  10. 19 ▸ Your potential if let or guard let on

    absoluteString will not be removed, it’s your job ▸ Tip: If you absolutely need to keep your code block you can use a do statement REAL WORLD PROBLEMS SOME APIS DO NOT RETURN OPTIONALS ANYMORE open class NSURL { open var absoluteString: String? { get } } public struct URL { public var absoluteString: String { get } } versus do { //your code here }
  11. REAL WORLD PROBLEMS OPTIONAL COMPARATORS DISAPPEARED 20 // FIXME: comparison

    operators with optionals were removed from the Swift Standard Libary. // Consider refactoring the code to use the non-optional operators. fileprivate func > <T: Comparable>(lhs: T?, rhs: T?) -> Bool { switch (lhs, rhs) { case let (l?, r?): return l > r default: return rhs < lhs } }
  12. 21 ▸ Dispatch APIs are not correctly migrated (at least

    at that time using Xcode 8.0) DispatchQueue.global(qos: .background).async { //do some work } DispatchQueue.global(qos: .default).asyncAfter(deadline: .now() + 1) { //do some work in 1s from now } ▸ dispatch_once doesn’t exist anymore ▸ Use lazily initialised globals or static properties REAL WORLD PROBLEMS GRAND CENTRAL DISPATCH SE-0044 & SE-0088
  13. 22 ▸ Remember Nullability Checking integrated into Swift 2.3 ▸

    ImplicitlyUnwrappedOptionals are considered like optionals now, but not all the time REAL WORLD PROBLEMS OBJECTIVE-C INTEROPERABILITY https://www.natashatherobot.com/swift-3-implicitly-unwrapped-optionals/ because File > New Project is a rare thing func valueUp(value: Int!) { // oldValue is an Int? // since value doesn't need to be type checked let oldValue = value // Int? // newValue is an Int, // since value was forced to unwrap // b/c it had to be type checked to do the addition let newValue = value + 1 // Int […] } valueUp(value: 10)
  14. 23 ▸ Swift 3 renamed a lot of objective-c based

    APIs automatically " ▸ Legacy swift annotations are still available ▸ nullability / generics ▸ NS_SWIFT_NAME / NS_REFINED_FOR_SWIFT / NS_SWIFT_UNAVAILABLE ▸ New annotations available ▸ NS_NOESCAPE to annotate your objective-c blocks (eg. @noespace) ▸ NSEXTENSIBLESTRING_ENUM to convert a string based obj-c enum to a struct REAL WORLD PROBLEMS OBJECTIVE-C INTEROPERABILITY https://realm.io/news/altconf-nikita-lutsenko-objc-swift-interoperability/ because File > New Project is a rare thing
  15. 24 ▸ I had to convert manually CGFloat.max to CGFloat.greatestFiniteMagnetude

    ▸ OptionSet are not converted as expected for default values : ▸ UIControlState() instead of .normal : it works but less readable ▸ Visibility changes : private becomes fileprivate etc… ▸ ⚠ Be aware of open versus public on your libraries REAL WORLD PROBLEMS SOME RANDOM NOTES SE-0067
  16. 25 ▸ map or flatmap returns LazyCollection types now :

    ▸ let list = Array(myLazyCollection) if you really need a Collection ▸ New compiler : new warnings like unused results ▸ You can add _ to discard it: _ = foo() ▸ returned result is secondary: @discardableResult on the function can also avoid this warning REAL WORLD PROBLEMS SOME RANDOM NOTES SE-0067
  17. 27 ▸ A (mostly) comprehensive list of Swift 3.0 and

    2.3 changes ▸ https://buildingvts.com/a-mostly-comprehensive-list-of-swift-3-0-and-2-3-changes-193b904bb5b1 ▸ Swift migration guide ▸ https://swift.org/migration-guide/ ▸ WWDC 2016 - Session 402 : What’s new in swift ▸ https://developer.apple.com/videos/play/wwdc2016/402/ ▸ AltConf - Advanced ObjC <-> Swift Interoperability ▸ https://realm.io/news/altconf-nikita-lutsenko-objc-swift-interoperability/ LET’S MIGRATE TO 3.0 REFERENCES David Bonnet - @iGranDav [email protected]