NSArray @property由NSMutableArray支持

时间:2011-12-06 21:42:20

标签: objective-c ios nsarray mutable

我已经定义了一个类,我希望公共属性看起来好像是由NSArray支持的。这很简单,但在我的情况下,实际的支持ivar是NSMutableArray

@interface Foo
{
    NSMutableArray* array;
}
@property (nonatomic, retain) NSArray* array;

@end

在我的实施文件(*.m)中我@synthesize属性,但我立即遇到警告,因为使用self.words与尝试修改NSArray相同。< / p>

这样做的正确方法是什么?

谢谢!

6 个答案:

答案 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设置你的实例变量;不要手工做。