Migrating from Swift 2 to 5 in 2020
Tags: ios, swift, pain
Published: 2020-09-03 06:47:26

**Task:** Build and publish an iOS app that built in 2016 using Swift 2 and kicked out from App Store.

Now is 2020. Since 2016 Apple introduced many new requirements. It needs to build an application with the latest Xcode but the last Xcode can not work with Swift version less than 4. However it has a feature to convert Swift code automatically to a newer version. But you can not to convert 2nd version to 5th. You have to convert 2 to 3, 3 to 4 and 4 to 5. Moreover it needs different versions of Xcode for each step.

## Common migration steps
* Install Xcode
* Convert code automatically by Xcode
* Update libraries
* Make it working by manual changes

# 2 to 3
[The official Swift 3 migration guide ](https://swift.org/migration-guide-swift3/)

So an old Xcode version's needed to open, compile and convert Swift 2 code. The valid (newest) Xcode version for Swift 2 is [Xcode 8.3.3](https://download.developer.apple.com/Developer_Tools/Xcode_8.3.3/Xcode_8.3.3.xip). Unfortunately Xcode 8.3.3 doesn't work on the latest OSX Catalina. It needs at least High Sierra or earlier. This struggle was solved using [VirtualBox](https://www.virtualbox.org).

When the correct OSX and Xcode were installed the code was converted automatically. The libraries were remaining. 

Firstly, it's good to have the version of the cocoa-pod CLI that fits that time. It's 1.3.1.

```bash
sudo gem install cocoapods -v 1.3.1
```

The key for a successful library update is to determine what version is suitable. It's easy if such information is on Pod page. E.g. for [RappleProgressHUD](https://cocoapods.org/pods/RappleProgressHUD) there is information about versions for Swift 4 and newer. Another way is to choose by time in [Podspec](https://github.com/CocoaPods/Specs/tree/master/Specs/4/5/5/RappleProgressHUD). Late 2017 fits Swift 3.

# 3 to 4
[The official Swift 4 migration guide ](https://swift.org/migration-guide-swift4/)

The next step is to convert Swift 3 to 4. It can be done using [Xcode 10.1](https://download.developer.apple.com/Developer_Tools/Xcode_10.1/Xcode_10.1.xip).

The libraries were migrated the same way as above.

There were several manual changes:

**Substring**
They introduced a new way to handle the ranges.

Swift 3
```swift
s[x...y]
```
Swift 4
```swift
String(
  s.substring(
    with: 
      s.index(s.startIndex, offsetBy: x)..
      <s.index(s.startIndex, offsetBy: y)
  )
)
```

**Explicit casting**
Variables of type "Any" should be explicitly casted.

Swift 3
```swift
array: NSArray
..
s = array[index]["id"] as? String
```

Swift 4
```swift
s = (array[index] as! NSDictionary)["id"] as? String
```

# 4 to 5
[The official Swift 5 migration guide ](https://swift.org/migration-guide-swift5/)

Finally, converting from Swift 4 to 5 is the easiest one and can be done on the latest Xcode 11. All code were converted automatically. Libraries were updated as above. Icons and launch screens were added for new sizes. 

Built. Published. Profit. ;)

Photo by [Jesse orrico](https://unsplash.com/@jessedo81?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/hard-work?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText)