5 things I wish I knew sooner about Swift

The places where Swift isn’t so intuitive.

Image by Dave See — source and licence (CC by 2.0).

It usually is. Intuitive, that is. Usually Swift is intuitive, with optionals and drag-and-drop kind of building of GUI elements.

But other times it isn’t intuitive at all. It redefines keywords from popular languages like C++ and Python , and the division between Storyboards and code can be incredibly confusing.

Here are 5 places that confused me when I started out. We will use Swift 5 in Xcode 11.5 using Storyboards —note that SwiftUI redefines the wheel again, but maybe for the better.

  1. Classes persist, structs do not
  2. Segues and unwind segues are done differently
  3. Protocol and delegate magic
  4. Prevent inheritance with final
  5. Public, internal, fileprivate and private, but no protected

  6. Classes persist, structs do not

Never mind what C++ has already established about the meanings of classes and structs (structs are classes with no private members). Just forget everything that already exists and learn it again — the Swift way.

Instead, in Swift, the key difference is: structs are passed by value, while classes are passed by reference.

Let’s take a look at an example using structs :

This fails to compile in the method that modifies the struct, because it is passed by value, and therefore cannot be modified:

No modifying structs.

Changing struct to class, on the other hand, works just fine:

  1. Segues and unwind segues are done differently

  • The first step in defining a normal segue is done in the storyboard.
  • The first step in defining an unwind segues is done in code.

Let’s start by creating two view controllers: MainViewController and SetDataViewController .

  • MainViewController has a simple message text field and a button.
  • SetDataViewController has a text field and a button.

Let’s hook it up such that pressing the button goes to the SetDataViewController . Click and drag from the button to the view controller to create a segue.

We can now name the segue:

And then add additional logic in the navigation section in MainViewController :

That works for the forward segue —but what about an unwind segue to go back?

To unwind, you start in the code. In the destination view controller MainViewController, add a returned method:

Then in the storyboard, hook up the unwind segue in the SetDataViewController . Click and drag from the button to the Exit at the top:

and select the returned method:

You can find the segue in the left hand side, and give it a name like returnedSegue as before:

That’s it!

  • For normal segues, first add the segue in the Storyboard. You can add an identity and modify it by name later in the code.
  • For unwind segues, first add the unwind function in the code in the destination view controller, then hook it up in the Storyboard.
  1. Protocol and delegate magic

Very frequently you will want to call a method of one view controller from another view controller. This is best done using protocols and delegates. If you are used to the idea of abstract base classes in C++ or Python, protocols are like an interface that a class promises to implement.

Let’s use the example from the last section.

  1. First define a new protocol called MainProtocol , which declares a method handleData . It inherites from AnyObject such that only classes can inherit from it.
  1. Then let MainViewController inherit from MainProtocol , and add an implementation for handleData .
  1. Add an optional weak delegate in SetDataViewController , and call it in the navigation code for the returnedSegue. Note that it must be weak to break the strong reference cycle (if you don’t use weak, the reference counts of the view controllers do not reach zero, so they don’t get deallocated).
  1. Finally, hook up the delegate in the MainViewController navigation:

This is the most general and powerful method for calling methods in different view controllers and passing data back and forth. The final MainViewController looks like this:

  1. Prevent inheritance with final

By default, you can inherit from any class you wish. The open keyword makes this explicit (but redundant):

The console will show Goodbye . We can change open to final to prevent inheritance:

This will prevent inheritance:

You can also apply it to a method rather than a whole class:

This allows inheritance but prevents override of the say method:

Using open and final you can control closely how your classes can be reused.

  1. Public, internal, fileprivate and private, but no protected

InPython you may be used to import statements, or include in C++ to include headers defining different methods.

Well it turns out in Swift , by default everything is just internal p̵u̵b̵l̵i̵c̵, meaning every class/method you define is available from any other file in your project (although not outside a module). Obviously, this is almost never what you want!

Even if you don’t care about it explicitly, note that leaving everything as internal increases compilation time. So it’s worthwhile using the other access levels appropriately: public, internal, fileprivate , and private .

  • public o̵r̵ ̵n̵o̵t̵ ̵g̵i̵v̵i̵n̵g̵ ̵a̵n̵y̵ ̵a̵c̵c̵e̵s̵s̵ ̵l̵e̵v̵e̵l means the method/class is available from anywhere in the project.
  • internal or not giving any access level means things can only be used from within the same module.
  • fileprivate means that things can only be used from within the same file.
  • private means you can only access it from within the same class you defined it in.

Note that private also has the usual meaning from C++ for classes, in that subclasses cannot access private attributes.

If you are wondering what the equivalent of the protected keyword from C++ is (protected attributes can only be accessed from an inherited class): there is none. It’s just public and private because…. Yep.

Final thoughts

Yes, Swift has lots of nice features and makes iOS programming like a breeze. Yes, it feels like Swift reinvented the wheel sometimes, and redefines keywords you already know. Yes, simple things can be so unintuitive between code and storyboards.

And yes, I wish I had known these things sooner.


Oliver K. Ernst
August 1, 2020

Read this on Medium