NSArray @property由NSMutableArray支持

Mat*_*y P 39 objective-c mutable nsarray ios

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

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

@end
Run Code Online (Sandbox Code Playgroud)

在我的实现文件(*.m)我@synthesize的属性,但我立即遇到警告,因为使用self.words与尝试修改一样NSArray.

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

谢谢!

Mar*_*ams 21

我会readonly NSArray在您的标头中声明一个并覆盖该数组的getter,以返回NSMutableArray在您的实现中声明的私有的副本.考虑以下.

foo.h中

@interface Foo

@property (nonatomic, retain, readonly) NSArray *array;

@end
Run Code Online (Sandbox Code Playgroud)

Foo.m

@interface Foo ()

@property (nonatomic, retain) NSMutableArray *mutableArray

@end

#pragma mark -

@implementation Foo

@synthesize mutableArray;

- (NSArray *)array
{
    return [[self.mutableArray copy] autorelease];
}

@end
Run Code Online (Sandbox Code Playgroud)

  • 使用某种东西制作属性的问题在于,调用者可以在一段代码中轻松地将代码写为aFoo.array 50次,从而创建了阵列的许多副本 - 这会导致性能死亡. (3认同)

sam*_*sam 14

基本上,将NSArray属性放在头文件中的类别中,并将NSMutableArray属性放在实现文件的类扩展中.像这样......

foo.h中:

@interface Foo
@end

@interface Foo (Collections)
@property (nonatomic, readonly, strong) NSArray *someArray;
@end
Run Code Online (Sandbox Code Playgroud)

Foo.m

@interface Foo ()
@property (nonatomic, readwrite, strong) NSMutableArray *someArray;
@end
Run Code Online (Sandbox Code Playgroud)

  • 在.m文件中调用`self.someArray`将使您可以访问`NSArray`并隐藏`NSMutableArray`,这使得该解决方案不太理想 (3认同)

Tom*_*sen 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];
}
Run Code Online (Sandbox Code Playgroud)

分配对象时,创建数组,当它死亡时,释放数组.

当仅使用'.'时会发生大的影响.运算符,它容易忽略非常低效的代码.访问者就是这样.另外 - 如果有人调用aFoo.array - 合同是访问foo的数组成员 - 但实际上它只是在调用时的副本.差异是真实的,它导致在这里发布的其他实现中的错误.


Reg*_*ent 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
Run Code Online (Sandbox Code Playgroud)

您在类扩展中添加了一个私有mutableArray属性,并使公众array只需转发到您的私有可变属性即可。

对于 ObjC 的最新语言扩展,我倾向于删除

{
    NSMutableArray* mutableArray;
}
Run Code Online (Sandbox Code Playgroud)

如果可能的话,完全阻止 ivar。

并通过综合定义 ivar,如下所示:

@synthesize mutableArray = _mutableArray;
Run Code Online (Sandbox Code Playgroud)

NSMutableArray *_mutableArray;这将为您生成一个实例。