【问题标题】:Do I need to override the getter for a property to return an immutable copy?我是否需要覆盖属性的 getter 以返回不可变副本?
【发布时间】:2014-08-04 03:00:30
【问题描述】:

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

#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];

}

【问题讨论】:

  • 你为什么不试试?

标签: objective-c properties accessor ivar


【解决方案1】:

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;
}

【讨论】:

  • 我应该怎么做才能使合成的getter返回一个副本?好吧,我尝试通过修改 getter 来修改您的示例代码以返回副本。但 myArrayIsIdentical 仍然会导致相同的匹配。
  • 您使用什么类进行测试?不可变类在复制时通常不会真正返回新对象,以节省内存。
  • 我复制了您的 ArrayReturner 类并将其更改为可变类(可变数组),事实证明我必须在可变类中同时实现 setter 和 getter 方法,以防我想要获取新的复制对象(数组)来自 MutableArrayReturner 类。
【解决方案2】:

因为您已经为数组属性指定了属性“copy”,所以无需重写 getter 和 setter。编译器将为您完成所有繁重的工作。

如果您改为指定“strong”,则 getter 和 setter 将如下所示:

-(NSArray *)assets
{
    return _assets;
}

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

这可能是个问题。

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

【讨论】:

  • 猜你的意思是 WWDC 会议——整个会议涵盖了很多主题。指定您正在谈论的会话会很有帮助,甚至可以提供视频链接。
  • 是的,会议,对不起。一个有用的链接可能是:developer.apple.com/videos/wwdc/2012 Sessions 405、413 或任何其他与内存管理和有效的 Objective-C 相关的内容
  • copy 不会让 getter 返回一个副本;属性说明符仅影响 setter。
  • 这个答案不正确;合成的 getter 不会返回一个副本:gist.github.com/woolsweater/38ad03759e6245bf6733 如果你想要这种行为,你必须自己编写。
猜你喜欢
  • 2012-02-12
  • 2011-08-25
  • 1970-01-01
  • 2018-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
相关资源
最近更新 更多