It is quite a seldom pattern for a class to expose a mutable property for a collection object as it seems to break encapsulation.
Nevertheless there are occasions when it might make sense: You could, for example return a KVO proxy for some internally managed collection (using KVC's mutableArrayValueForKey:
).
In these cases is does not really matter whether or not to declare the getter as a property or plain method. In case of properties it should not be a copy
property, though.
To make this a little clearer here's an example. We have a class that declares a single public getter:
@interface Foo : NSObject
@property (strong, readonly) NSMutableArray *publicBars;
@end
The implementation manages an encapsulated, private mutable array named _bars
:
@implementation Foo
{
NSMutableArray *_bars;
}
The elements of this array are exposed by KVC to-many accessors:
- (NSUInteger)countOfBars
{
return [_bars count];
}
- (id)objectInBarsAtIndex:(NSUInteger)idx
{
return _bars[idx];
}
- (void)insertObject:(id)object inBarsAtIndex:(NSUInteger)idx
{
if (_bars == nil)
_bars = [NSMutableArray array];
[_bars insertObject:object atIndex:idx];
}
- (void)removeObjectFromBarsAtIndex:(NSUInteger)idx
{
[_bars removeObjectAtIndex:idx];
}
Here's the fancy part: We are implementing the public property by returning a KVC proxy that reflects and mutates the internal state without exposing internal ivars. It changes the internal array by only using the public accessors defined above.
- (NSMutableArray *)publicBars
{
return [self mutableArrayValueForKey:@"bars"];
}
@end
We can use the proxy to change the internal collection:
Foo *foo = [[Foo alloc] init];
NSMutableArray *bars = foo.publicBars;
[bars addObject:@1];
[bars addObject:@2];
[bars removeObjectAtIndex:0];
// Now the internal _bars array is @[ @2 ].
There are actual examples of this and similar patterns in Cocoa. For example there is -[NSTextView textStorage]
that returns the internal backing store (an object derived from NSMutableAttributedString
). Though not a collection object this is a mutable object which passes mutations to its host object, the text view.