我已经定义了一个类,我希望公共属性看起来好像是由NSArray
支持的。这很简单,但在我的情况下,实际的支持ivar是NSMutableArray
:
@interface Foo
{
NSMutableArray* array;
}
@property (nonatomic, retain) NSArray* array;
@end
在我的实施文件(*.m
)中我@synthesize
属性,但我立即遇到警告,因为使用self.words
与尝试修改NSArray
相同。< / p>
这样做的正确方法是什么?
谢谢!
答案 0 :(得分:21)
我会在您的标头中声明readonly
NSArray
并覆盖该数组的getter,以返回您的实现中声明的私有NSMutableArray
的副本。请考虑以下事项。
<强> foo.h中强>
@interface Foo
@property (nonatomic, retain, readonly) NSArray *array;
@end
<强> Foo.m 强>
@interface Foo ()
@property (nonatomic, retain) NSMutableArray *mutableArray
@end
#pragma mark -
@implementation Foo
@synthesize mutableArray;
- (NSArray *)array
{
return [[self.mutableArray copy] autorelease];
}
@end
答案 1 :(得分:14)
基本上,将NSArray属性放在头文件中的类别中,将NSMutableArray属性放在实现文件中的类扩展中。像这样......
foo.h中:
@interface Foo
@end
@interface Foo (Collections)
@property (nonatomic, readonly, strong) NSArray *someArray;
@end
Foo.m
@interface Foo ()
@property (nonatomic, readwrite, strong) NSMutableArray *someArray;
@end
答案 2 :(得分:5)
简单:
1)不要使用属性。
2)代码简化为:
- (NSArray *)currentArray {
return [NSArray arraywithArray:mutableArray]; // need the arrayWithArray - otherwise the caller could be in for surprise when the supposedly unchanging array changes while he is using it.
}
- (void)setArray:(NSArray *)array {
[mutableArray setArray:array];
}
当分配对象时,创建数组,当它死亡时,释放数组。
当仅使用'。'时会发生大的影响。运算符,它容易忽略非常低效的代码。访问者就是这样。另外 - 如果有人调用aFoo.array - 合同是访问foo的数组成员 - 但实际上它只是在调用时的副本。差异是真实的,它导致在此处发布的其他实现中的错误。
答案 3 :(得分:4)
更新:此答案无效。请使用以下建议的解决方案之一。
现在,您可以执行以下操作:
Foo.m:
@implementation Foo {
NSMutableArray* _array;
}
@end
foo.h中:
@interface Foo
@property (readonly, strong) NSArray* array;
@end
您仍然可以通过ivar从实现内部寻址可变的_array,并且可以通过immutable属性访问它。不幸的是,这并不能保证其他人不能将其转换为NSMutableArray并进行修改。为了更好地防止白痴,您必须定义访问器方法并返回不可变副本,但在某些情况下这可能非常昂贵。
我实际上同意上面的一条评论,如果你需要返回一些只读数据,那么使用简单的访问器方法会更好,它肯定不那么模糊。
答案 4 :(得分:2)
那是因为你的属性必须与实际的ivar类类型匹配。
可能的解决方案/解决方法:
//Foo.h:
@interface Foo
{
NSMutableArray* mutableArray;
}
@property (readwrite, nonatomic, retain) NSArray* array;
//or manual accessor declarations, in case you're picky about wrapper-properties.
@end
//Foo.m:
@interface Foo ()
@property (readwrite, nonatomic, retain) NSMutableArray* mutableArray;
@end
@implementation
@synthesize mutableArray;
@dynamic array;
- (NSArray *)array {
return [NSArray arrayWithArray:self.mutableArray];
}
- (void)setArray:(NSArray *)array {
self.mutableArray = [NSMutableArray arrayWithArray:array];
}
@end
您在类扩展中添加了私有mutableArray
属性,并将公开array
简单地转发到您的私有可变属性。
使用ObjC的最新语言扩展我倾向于删除
{
NSMutableArray* mutableArray;
}
如果可能的话,完全阻止ivar。
通过合成来定义ivar,如下:
@synthesize mutableArray = _mutableArray;
将为您生成NSMutableArray *_mutableArray;
个实例。
答案 5 :(得分:0)
最简单的答案:您的属性类型(NSArray)与您的实例变量类型(NSMutableArray)不匹配。
这是你不应该定义自己的支持变量的另一个好理由。让@synthesize设置你的实例变量;不要手工做。