可变集合作为属性的最佳实践 [英] Best practices for mutable collections as properties
问题描述
我打算使用 NSMutableDictionary
属性来存储游戏数据(例如得分,设置等......)。
I was planning to use an NSMutableDictionary
property for storing game data (such as score, settings, etc...).
@property (nonatomic, copy) NSMutableDictionary *gameData;
在研究为什么没有mutablecopy选项的情况下我找到了这个讨论,接受的答案陈述:
In researching why there is no "mutablecopy" option for properties I found this discussion, for which the accepted answer states:
正确的做法是不使可变数组成为属性
the right way to do it is not to make the mutable array a property
那么在现代Objective-C中将可变集合作为属性处理的最佳方法是什么?
What then is the best way to handle mutable collections as properties in modern Objective-C?
推荐答案
对于类来说,暴露集合对象的可变属性是一种很少的模式,因为它似乎打破了封装。
It is quite a seldom pattern for a class to expose a mutable property for a collection object as it seems to break encapsulation.
然而 的情况可能有意义:例如,你可以为一些内部管理的集合返回一个KVO代理(使用 KVC的 mutableArrayValueForKey:
)。
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:
).
在这些情况下,是否将getter声明为属性或普通方法并不重要。如果是属性,它不应该是 copy
属性。
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.
为了使这个更清楚,这里是一个例。我们有一个声明一个公共getter的类:
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
该实现管理一个名为<的封装的私有可变数组code> _bars :
@implementation Foo
{
NSMutableArray *_bars;
}
此数组的元素由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];
}
这是花哨的部分:我们通过返回一KVC代理反映和改变内部状态而不暴露内部ivars。它仅通过使用上面定义的公共访问器来更改内部数组。
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 ].
在Cocoa中有这个和类似模式的实际例子。例如, - [NSTextView textStorage]
返回内部后备存储(从 NSMutableAttributedString
派生的对象)。虽然不是集合对象,但它是一个可变对象,它将突变传递给它的宿主对象,即文本视图。
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.
这篇关于可变集合作为属性的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!