我打算使用一个NSMutableDictionary
属性来存储游戏数据(如分数、设置等)。
@property (nonatomic, copy) NSMutableDictionary *gameData;
在研究为什么属性没有“mutablecopy”选项时,我找到了这个讨论,其中被接受的答案说:
那么,现代Objective-C中处理可变集合作为属性的最佳方式是什么?正确的方法不是将可变数组作为属性
我打算使用一个NSMutableDictionary
属性来存储游戏数据(如分数、设置等)。
@property (nonatomic, copy) NSMutableDictionary *gameData;
那么,现代Objective-C中处理可变集合作为属性的最佳方式是什么?正确的方法不是将可变数组作为属性
mutableArrayValueForKey:
)。copy
属性。@interface Foo : NSObject
@property (strong, readonly) NSMutableArray *publicBars;
@end
_bars
:@implementation Foo
{
NSMutableArray *_bars;
}
- (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。它只使用上面定义的公共访问器来更改内部数组。
- (NSMutableArray *)publicBars
{
return [self mutableArrayValueForKey:@"bars"];
}
@end
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
的对象)。虽然不是一个集合对象,但它是一个可变对象,可以将其变化传递给其主机对象——文本视图。
在我看来,你可以很好地使用可变属性 - 因为在Objective-C中,属性不仅用于封装,还用于内存管理(通过ARC)。
然而,你应该将此属性保留在实现文件中,并将其公开为其他类的非可变、只读部分。
//your_header_file.h
@interface YouClass : NSObject
@property (readonly) NSDictionary *gameState;
@end
//your_implementation_file.m
@interface YouClass ()
@property (nonatomic, strong) NSMutableDictionary *gameState;
@end
@implementation SomeClass
//deal with mutable state here
@end
编辑:
另外,由于可变集合通常不是线程安全的,请确保您始终从同一线程更改它们。
- (void)storeObject:(id)object forSetting:(NSString *)settingName;
- (id)objectForSetting:(NSString *)settingName;
NSKVOCompliance
属性或类似的东西。静态分析器甚至可以使用它来生成有关错误观察的警告。 - Nikolai Ruhe