Expose Mutable Properties as Immutable
It is often useful to expose mutable properties as immutable in API design. The canonical way to do it in Objective-C is to use the combination of:
- a public read-only property of immutable type and,
- a private ivar of mutable type to back the property.
For example:
// List.h
@interface List : NSObject
@property (nonatomic, readonly) NSArray *items;
@end
// List.m
@interface List () {
NSMutableArray *_ items;
}
@end
You can not use this design pattern in Swift because Swift does not have ivars. However, Swift has calculated properties. Clever people figured out that we can use a private stored property to back a public calculated property:
class List: NSObject {
public var items: [ListItem] {
return _items
}
private var _items: [ListItem]
}
But I found a better way, using setter access control:
class List: NSObject {
public private(set) var items: [ListItem]
}
Outside List
class, items
is not only read-only:
list.items = [item1, item2] // Compilation error: Cannot assign to the result of this expression.
but also immutable:
list.items.append(item1) // Compilation error: Immutable value of type '[ListItem]' only has mutating members named 'append’.
Now we can say Swift is more concise than Objective-C, as least for this API design.