In today's tutorial, I want to show you a little know feature of access control in Swift. You probably know that the Swift language defines five access levels:
open
public
internal
fileprivate
private
But what do you do if you want to declare a property internal, public, or open, but you don't want anyone but the instance to set the property? You could solve this problem declaring the property private and defining a computed property that acts as a getter for the private property.
class CoreDataManager {
...
private lazy var mainManagedObjectContext: NSManagedObjectContext = {
// Initialize Managed Object Context
let managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
// Configure Managed Object Context
managedObjectContext.parent = self.privateManagedObjectContext
return managedObjectContext
}()
public var managedObjectContext: NSManagedObjectContext {
return mainManagedObjectContext
}
...
}
The mainManagedObjectContext
property of the CoreDataManager
class is declared private and we define a public computed property that provides access to the mainManagedObjectContext
property. The result is that the mainManagedObjectContext
can only be set by the CoreDataManager
instance, but it can be accessed through the managedObjectContext
computed property by other objects.
This works fine. But Swift wouldn't be Swift if there wasn't a more elegant solution. Take a look at the updated example below. This is an example from Building the Perfect Core Data Stack.
class CoreDataManager {
...
public private(set) lazy var mainManagedObjectContext: NSManagedObjectContext = {
// Initialize Managed Object Context
let managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
// Configure Managed Object Context
managedObjectContext.parent = self.privateManagedObjectContext
return managedObjectContext
}()
...
}
The mainManagedObjectContext
property is declared public, which means we can remove the managedObjectContext
computed property. To make sure only the CoreDataManager
instance can set the mainManagedObjectContext
property we assign the setter a lower access level by using the private(set)
modifier. This also works for fileprivate
and internal
access levels.