Swift 3 Conversion Steps. Or "The 9 steps to Swift bliss"
October 10, 2016
Estimated reading time 8 minutes
Every time Apple decided to bring out a new version of Swift, I'd dive headfirst and start the conversion — the sooner the better. None of the past versions were such a nightmare as from Swift 2.1 to 3.0.
These notes I wrote down while converting our project to a Swift 3.0 project. Hopefully someone finds them useful. If you have comments or like to see something added, please let me know.
Let me start with a big fat warning.
⚠️ Don’t ‘Update to recommended setting’. Do this later. ⚠️
So the steps to undertake and achieve Swift bliss are this:
- Create new branch.
- Change
Podfileto reflect the following:platform :ios, '9.0', use_frameworks! inhibit_all_warnings! - Update dependencies with a
$ pod update - Commit changes to git
- Convert to Swift 3 syntax
- Commit changes
- Fix errors (loads of them)
- Lint
- Commit changes
Breaking changes in Swift 3 Conversion
So first things first – you are not alone in this. Apple has created a good starting point with their migration guide. Read it before starting the conversion and keep it as a reference while converting.
- New keywords. It takes some getting used to. Current behavior changed too.
- String indexes and Ranges work different
ErrorType⇒Error- All enum cases are now lowercase
- Use of
_in methods to supres/omit names parameters. Named parameters are now default. .[upper/lower]caseString⇒.[upper/lower]cased()because it is mutating.forcan now be used for named parameters.addTarget(self, action: ..., for: ...)containsString()⇒contains().objectForKey(...)⇒object(forKey: ...)- Colors are not a function call anymore but class var
wherekeyword in optional binding not needed anymore, you can now just use a commaCGColorRef⇒CGColor- when using multiple properties in single
guardyou must useletfor each property. Also in optional binding. UIControlState.Normal⇒UIControlState()UIView.animateWithDuration⇒UIView.animate(withDurationNSFetchedResultsControlleris now a GenericString(self)⇒String(describing: self).- Dispatch Queues tend to f-up the migrator wizard syntax.
Errors:
Argument label does not match any available overloads
Solution: In the conversion to Swift 3 something went haywire, look in the original implenmentation wat the function signature is you want to implement.
Ambiguous reference
Solution: You need to provide more Type detail. Usually this is fixed by adding an : Type or an as? Type or with an optional binding if let ....
Method cannot be declared because its parameter uses an internal type
Solution: Take a close look at the access modifiers. The above states that there are no (and thus internal), or wrong access modifiers used.
Instance method 'method(param:)' nearly matches optional requirement 'method(in:)' of protocol 'SomeProtocol'
Solution: In some cases the Swift migrator fails but does find something that looks like that method signature. Usually fixable by searching and copying the orginal protocol for the method signature.
Expression of type "SomeType?" is unused.
Solution: Before Swift 3, all methods had a “discardable result” by default. In Swift 3 the behavior is flipped – all methods now warn that the return value is not captured. If you want to tell the compiler that the warning isn’t necessary, you add @discardableResult before the method declaration.
API Changes:
Apple keeps a list of API’s that changed, the ones that have a Swift method signature. This way you can cross reference if you get any ‘Instance method nearly matches optional requirement of protocol’ errors.
When you use your own libraries with Cocoapods.
Errors with Generics
I’ve hit a couple of compiler errors which are already filled with Apple. Try to work around it or find a different solution to your problem.
Once all your errors are gone and you linted your project with SwiftLint
Now you can update to the latest project settings.
Now - we've been through a lot of pain an frustration, go make yourself a cup-o-something and pat yourself on the back. "Well done you". You deserved it.
Let's hope Apple does not make breaking changes going forward with Swift.