Swift 4 Access Levels

You may not have noticed but there was a small but important change to the private access level in Swift 4. After a quick recap of the five levels I cover what has changed in Swift 4, what do you need to know when migrating from Swift 3 and what is the point of fileprivate now?

The Five Access Levels of Swift 4

To recap Swift 4 has the same five access levels as Swift 3. In order from most open to most restricted:

Notes:

How Did private Access Change?

In Swift 3 if you wanted an extension to have access to a private property or method you had to use fileprivate. Consider this Swift 3 code for a view controller with a private property:

class RootViewController: UIViewController {
  private var started = false
}

If I have an extension of the class in the same file, using Swift 3, it cannot access the private property:

extension RootViewController {
  func doSomething {
    if started { ... } // Error - no private access (Swift 3)
  }
}

Since extensions are a common Swift technique this led to the widespread use of fileprivate when splitting a type between a base declaration and one or more extensions:

// RootViewController.swift
class RootViewController: UIViewController {
  fileprivate var started = false
}

extension RootViewController {
  func doSomething {
    if started { ... } // fileprivate access allowed
  }
}

I think it is fair to say this is now considered unnecessarily complicated. Swift 4 limits the need for fileprivate by widening the scope of private access to include extensions. So this now works fine in Swift 4:

// RootViewController.swift
class RootViewController: UIViewController {
  private var started = false
}

extension RootViewController {
  func doSomething {
    if started { }     // private access allowed (Swift 4)
  }
}

Note that the extension still has to be in the same source file for private access.

// RootViewController+Extension.swift
extension RootViewController {
  func doExtra {
    if started { }     // no private access from here
  }
}

So When Do I Use fileprivate?

So what is the point of fileprivate now? Well you should need it a whole lot less with Swift 4. One example, suppose I have a Widget class with private and fileprivate methods:

// Widget.swift
class Widget {   
  private func privateMethod() { ... }
  fileprivate func fileprivateMethod() { ... }
}

Neither method is visible outside of the source file but what about a subclass in the same source file? It is not an extension of the Widget class so it cannot access the private method but it can access the fileprivate method:

// Widget.swift
class SpecialWidget: Widget {
  func start() {
//  privateMethod()      // No access to private method
    fileprivateMethod()  // fileprivate access allowed
  }
}

I’m Upgrading From Swift 3 - What Should I Do?

The short answer is probably not much. You can replace fileprivate with private if you were using it for extension access - but you are not forced to. Your Swift 3 code will still work with one possible exception.

If you are unlucky enough to have used the same name for private methods in a base declaration and one or more extensions in the same source file you will get an error with Swift 4:

struct Person {
  private func helperMethod() { ... }
}

extension Person {
  private func helperMethod() { ... }
  // Invalid redeclaration
}

The increased scope of private in Swift 4 means that you will have to rename the duplicate method names.

Further Reading

Never Miss A Post

Sign up to get my iOS posts and news direct to your inbox and I'll also send you a PDF of my WWDC Viewing Guide

    Unsubscribe at any time. See privacy policy.

    Archives Categories