Software, Tech & Coding simplified.

Swift fileprivate vs private

In Swift:

  • fileprivate means an entity that is accessible anywhere in that file.
  • private means an entity that cannot be accessed anywhere except for the enclosing type, such as a class.

In a sense, fileprivate means “private, but not in this file”.

For example:

class Example {
    fileprivate var number1: Int = 10
    private var number2: Int = 10
}

let ex = Example()

print(ex.number1) // Succeeds
print(ex.number2) // Fails
  • Here number1 was successfully printed, because it is fileprivate and thus accessible in the file.
  • The number2 was not printed because it is private, and thus not accessible outside the class.

This is the quick answer.

However, there is a lot more you need to understand about private and fileprivate access control levels. Let’s take a deeper look at private and fileprivate access levels in Swift.

Access Control Modifiers in Swift

Let’s take a look at the access levels in Swift.

In total, there are five access control levels at your disposal.

  • open. Makes it possible to inherit a class/override a function outside of the module.
  • public. Reveals an entity outside of the module it is defined in.
  • internal. This is the default access level in Swift. Internal access means a declaration is visible in the entire module it is declared in.
  • fileprivate. Makes a property/function visible within the whole file, but not outside of it
  • private. Makes a property/function inaccessible outside its enclosing type.

In this article, we are going to focus on the two lowest access levels, that is, private and fileprivate.

Private in Swift

Private is the most restrictive access control level in Swift.

When you declare something as private, it can only be accessed within the enclosing type and its extensions.

For example:

class Example {
    private var number1: Int = 10
    func change() {
        // Works!
        self.number1 = 20
    }
}

extension Example {
    func changeAgain(){
        // Works!
        self.number1 = 30
    }
}

func show() {
    let e = Example()
    // Fails!
    print(e.number1)
}

Here the number1 is private property. It can be updated in the class itself as well as in the extension to that class. However, it cannot be accessed outside of the class. This is why the show() function causes an error.

This is what it means to be private in Swift.

When Use Private in Swift

Declaring something private ensures it is not accessed from where it is not supposed to be accessed. Also, when an entity is private, Xcode does not show it in the code suggestions.

For example, something that is only relevant to that specific class should be declared private.

For example, a helper function can be declared private so that someone does not accidentally call it:

struct Person {
    let name: String
    let weightKilos: Double

    private func pounds() -> Double {
        return weightKilos * 2.2048
    }

    func info(){
        print("Hi, I am \(name). I weigh \(pounds()) pounds")
    }
}

Here the pounds() method is private.

This is because our intention is to only use it in the info() function to convert the weight to pounds. We do not want a developer to call the pounds() function, so we make it impossible to do it by accident.

Fileprivate in Swift

In Swift, fileprivate is the second most restrictive access control level.

When you declare an entity fileprivate, it can only be accessed within the same file.

Let’s see an example.

class Example {
    fileprivate var number1: Int = 10
    func change() {
        // Works!
        self.number1 = 20
    }
}

extension Example {
    func changeAgain(){
        // Works!
        self.number1 = 30
    }
}

func show() {
    let e = Example()
    // Works!
    print(e.number1)
}

Now, number1 is accessible everywhere in that file.

However, if you put the show() function into a separate file, you are going to see an error. This is because number1 is not accessible outside the file where it is declared.

When Use fileprivate in Swift

Fileprivate restricts access within the same source file.

Notice that these days you are almost always going to use private over fileprivate!

Back in Swift 3, if you wanted to access a private member in an extension, you had to make the member fileprivate.

This made the code more complicated for no apparent reason.

Due to the popularity of extensions, private access level was relaxed in Swift 4. This made accessing private members possible inside extensions in the same file. So in essence, fileprivate turned into private in Swift 4.

This leaves very little if any use cases for fileprivate in Swift 4+.

The only reason to use the fileprivate is to restrict the access of an entity to a single file, but not outside of it.

However, writing code with multiple entities in the same file is against the best practices. In Swift, it is suggested to define entities to separate files. Following these best practices makes fileprivate completely redundant.

As a matter of fact, I could not come up with nor find any valid use case for fileprivate anymore.

Anyway, let’s see another example of using fileprivate where we split code into separate files.

  • Let’s implement a class called Example with a fileprivate property number.
  • Let’s implement another class ExampleShower (in the same file) that prints the fileprivate property name of an Example object.
class Example {
    fileprivate var number: Int = 10
}

class ExampleShower {
    func showResult(example: Example) {
        print(example.number)
    }
}

This causes no errors.

However, let’s separate these two classes into different files:

Example.swift

class Example {
    fileprivate var number: Int = 10
}

ExampleShower.swift

class ExampleShower {
    func showResult(example: Example) {
        print(example.number)
    }
}

Even though the code remains unchanged, now there is an error that says:

'number' is inaccessible due to 'fileprivate' protection level

This error is caused by the fact that we try to access a fileprivate property on another file.

Based on what you have learned so far you probably already have a good idea of what is the difference between private and fileprivate. But let’s make a comparison anyways.

Private vs fileprivate in Swift

A fileprivate entity is accessible inside the file.

A private entity is only accessible to the enclosing type, such as a class.

For instance, let’s create a class called Example with:

  • A private property number1.
  • A fileprivate property number2.

And let’s also create a function show() that prints both of these properties out:

Here, accessing number1 is not possible because it is private property. But accessing number2 does not cause any problems. This is because it is a fileprivate property that can be accessed within the same file.

However, let’s separate the Example class and the show() function into separate files:

Now both number1 and number2 are inaccessible.

  • The number1 cannot be accessed because it is private.
  • The number2 cannot be accessed either because it is fileprivate, thus accessible in Example.swift only.

Conclusion

Today you learned what is the difference between private and fileprivate access levels in Swift.

To recap, fileprivate means that only the file has private access to the entity. The code in other files cannot access a fileprivate entity.

These days, you are rarely going to use fileprivate. Instead, you are going to use private most of the time.

Thanks for reading.

Happy coding!

Further Reading

50 Swift Interview Questions

Share

Share on twitter
Share on linkedin
Share on facebook
Share on pinterest
Share on email