可变集合作为属性的最佳实践 [英] Best practices for mutable collections as properties

查看:80
本文介绍了可变集合作为属性的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打算使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆