I’ve been upgrading the try! Swift app to Swift 3.0 for what feels like 3 days now (I’ve had to take a lot of breaks to be in the right patient mindset, especially with not knowing how many more errors will come up after the immediate ones were fixed).

But anyway, this morning my BUILD SUCCEEDED!! I fixed the final warnings (almost) and tried out the app to see that it works generally. I still have time to fix any bugs in the future before the next version goes in production.

And although the process was definitely frustrating, a lot of the things that needed fixing were very repetitive. For example, the String API has added a new (and very ugly IMHO) describing parameter:

I had to fix these with the describing and .self over and over again during my Swift 3.0 upgrading process. As soon as I finished the upgrade, I knew I had to fix this issue. After all, hopefully the String API will be fixed back to having no describing parameter in Swift 4 – I want to refactor this repetitive change in only one place in the future!

The Refactor

Luckily, in this case, I knew just the solution! In fact, I talked about this solution in my POP talk… I should definitely have implemented this earlier, but when I first started making the app, I didn’t know about it, and it hasn’t been a big enough issue to actually do the refactor until this painful Swift 3.0 upgrade 😬

All it took was a few minutes and a few protocols! A timely reminder of how awesome Swift actually is! For a more detailed explanation, make sure to watch my talk or read about it from the source here. Otherwise, here is the quick version:

First, create a Protocol with a default variable for generating the nib name string from the class name:

Swift

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

protocolNibLoadableView: class{}

extensionNibLoadableView whereSelf: UIView{

staticvarnibName: String{

// notice the new describing here

// now only one place to refactor if describing is removed in the future

returnString(describing:self)

}

}

// Now all UITableViewCells have the nibName variable

// you can also apply this to UICollectionViewCells if you have those

// Note that if you have some cells that DO NOT load from a Nib vs some that do,

// extend the cells individually vs all of them as below!

// In my project, all cells load from a Nib.

extensionUITableViewCell: NibLoadableView{}

Next, do the same thing to generate the reuse identifier string from the cell class:

Swift

1

2

3

4

5

6

7

8

9

10

11

protocolReusableView: class{}

extensionReusableView whereSelf: UIView{

staticvarreuseIdentifier: String{

returnString(describing:self)

}

}

extensionUITableViewCell: ReusableView{}

Now the good stuff! You can take advantage of the above protocols to simplify the nib registration and cell dequeuing: