Just one week left till WWDC 2017! I am expecting much more power given to developers in SiriKit and a couple of surprises. I guess you are waiting for some new APIs too 😬.

The new Apple developer season is not only about APIs, OSes but also about Swift update. Swift 4 is coming. There are no big breaking changes, backwards compatibility will be ensured. Some neat things there. Ole Begemann has created a neat playground with all news.

private gets boost in Swift 4

Among all new features, one thing came particularly to my interest - visibility of private declaration in extensions in the same file (SE-0169).

About a year ago, in Issue #22 we have discussed, and complained a bit about the new fileprivate. As much as splitting implementation to extensions is considered a good practice, fileprivate was initially intended to be used rarely. In reality it was used a lot. We’ve had to update our code in around 200 places 😅.

But this will change with Swift 4. private declaration will be accessible in type extensions in the same file. This change concerns only extensions; subclasses in the same files are not in scope.

private in Swift 3 vs. Swift 4

Take a look at this sample code:

// ListViewController.swift

class ListViewController: UIViewController {

	private let tableView = UITableView()
	private let items: [String] = ["Item 1", "Item 2", 	"Item 3"]

// ...
}

extension ListViewController: UITableViewDataSource {
	func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count // Inaccessible in Swift 3
    }
    
    //...
}

This code is invalid in Swift 3 as items is not accessible in extension. In Swift 3 items would require fileprivate However in Swift 4 this will be valid.

So what happens with fileprivate now?

It will stay, but will be used as intended - rarely. Take a look at the following example:

struct A {
    fileprivate var a: Int = 1
    private var b: Int = 2
}

struct B {
    private var c: A = A()
    
}

extension B {
    func foo(){
        print(c.a) //accessible
        //print(c.b) //💥inaccessible
    }
}

extension A {
    func boo(){
        print(a) //accessible
        print(b) //accessible
    }
}

B().foo()
A().boo()

Property a is marked with fileprivate so it will be visible even for other types within scope of this file. However property b is marked with private so it remains restricted to its owning type extension.

Swift 4 access control diagram?

Well, our previous diagram remains valid. Just a bump in language version:

Summary & References

If SE-0169 makes it, fileprivate will have less prominent role. Luckily your Swift 3 code will continue to work, as fileprivate is now just a bit less restrictive than private. For me, in practice this means I will probably forget about fileprivate existence.