Swift 3 Conversion Steps. Or "The 9 steps to Swift bliss"

October 10, 2016


Estimated reading time 8 minutes

Bliss 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:

  1. Create new branch.
  2. Change Podfile to reflect the following: platform :ios, '9.0', use_frameworks! inhibit_all_warnings!
  3. Update dependencies with a $ pod update
  4. Commit changes to git
  5. Convert to Swift 3 syntax
  6. Commit changes
  7. Fix errors (loads of them)
  8. Lint
  9. 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
  • ErrorTypeError
  • 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.
  • for can 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
  • where keyword in optional binding not needed anymore, you can now just use a comma
  • CGColorRefCGColor
  • when using multiple properties in single guard you must use let for each property. Also in optional binding.
  • UIControlState.NormalUIControlState()
  • UIView.animateWithDurationUIView.animate(withDuration
  • NSFetchedResultsController is now a Generic
  • String(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.

Cocoapods fails when linting.

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.