我是否需要覆盖属性的getter以返回不可变副本?

时间:2014-08-04 03:00:31

标签: objective-c properties accessor ivar

假设我有一个包含可变数组的类。我想确保如果其他类要求数组,它们将获得一个非可变类型,但在拥有类中,它实际上是NSMutableArray的一个实例,因此我可以添加和删除项。< / p>

#import "Person.h"

@class Asset;

@interface Employee : Person

{
    NSMutableArray *_assets;
}

@property (nonatomic,copy) NSArray *assets;

-(void)addAssets:(Asset *)a;

问题是,我是否必须将访问器方法修改为类似的东西,还是会自动表现得像我想要的那样?

#import "Employee.h"
#import "Asset.h"

@implementation Employee

/* Accessors for assets properties
-(NSArray *)assets
{
    return [_assets copy];
}

-(void)setAssets:(NSArray *)assets
{
    _assets = [assets mutableCopy ];

}
*/

-(void)addAssets:(Asset *)a
{
    //is assets nil?

    if (!_assets) {
        //Create Array
        _assets = [[NSMutableArray alloc]init];
    }
    [_assets addObject:a];

}

2 个答案:

答案 0 :(得分:2)

ppalancica's answer不正确。 copy属性仅表示设置者在设置属性时获取副本。合成的getter将返回副本。您必须自己实施该行为:

- (NSArray *)assets
{
    return [_assets copy];
}

您可能想制作制作副本的内部访问者。你也可以redeclare the property privately;然后将签订客户端代码以将其请求的数组视为不可变的。

此代码演示了合成的getter返回未复制的对象:

#import <Foundation/Foundation.h>

@interface ArrayReturner : NSObject

@property (copy, nonatomic) NSArray * array;

@end

@implementation ArrayReturner
{
    NSMutableArray * _array;
}

- (BOOL)myArrayIsIdenticalTo:(NSArray *)otherArray
{
    return _array == otherArray;
}

@end

int main(int argc, const char *argv[])
{
    @autoreleasepool {

        ArrayReturner * a = [ArrayReturner new];
        [a setArray:@[@1, @2]];
        NSArray * returnedArray = [a array];
        // Does not throw
        NSCAssert([a myArrayIsIdenticalTo:returnedArray],
                  @"Returned array is a separate instance.");
    }

    return 0;
}

答案 1 :(得分:0)

因为你已经指定了属性&#34; copy&#34;对于数组属性,不需要覆盖getter和setter。编译器将为您完成所有繁重的工作。

如果你指定&#34; strong&#34;相反,getter和setter看起来像:

-(NSArray *)assets
{
    return _assets;
}

-(void)setAssets:(NSArray *)assets
{
    _assets = assets;
}

这可能是个问题。

实际上有一个WWDC会议解释了所有这些细节。对于NSString属性,建议使用copy,你可以在iOS SDK框架中看到它很多。