4

我刚刚阅读了Craig Hockenberry的一篇关于ARC 和 copy的简短博客文章。我现在的问题是传递给分配给实例变量的初始化程序的参数是否应该始终使用copy?还是取决于实例变量的类型?

#import "MyObject.h"

@implementation MyObject {
    SomeType *_ivar1;
    SomeOtherType *_ivar2;
}

-(id)initWithParam1:(SomeType *)param1 andParam2:(SomeOtherType *)param2
{
    if ((self == [super init])) {
        _ivar1 = [param1 copy]; // Always good
        _ivar2 = [param2 copy]; // practice?
    }

    return self;
}

@end
4

2 回答 2

4

我认为理解这篇文章的关键在于这个声明:

因为我认为在 -init 期间使用访问器是一个坏主意,@property所以从不使用由定义的复制语义,并且 ARC 很乐意保留引用而不是复制它。

我认为克雷格是在专门谈论以下案例:

@interface MyObject : NSObject {
    SomeType *_ivar1;
}
-(id)initWithParam1:(SomeType *)param1;
@property (copy, nonatomic) SomeType* prop1;
@end

@implementation MyObject
@synthesize prop1 = _ivar1;
-(id)initWithParam1:(SomeType *)param1 {
    if ((self == [super init])) {
        /*
        Craig could have called

        self.prop1 = param1;

        but he believes that it's a bad idea to call accessors
        from the initializer, so he calls copy explicitly.
        */
        _ivar1 = [param1 copy];
    }
    return self;
}
@end
于 2012-07-06T18:52:38.943 回答
2

取决于变量的类型和意图。

对于简单的类型——NSString、NSArray、NSNumber 等等——你使用复制是因为你通常希望存储的类型是不可变的。也就是说,拥有一个firstName可以通过传入NSMutableString.

对于更复杂的类——封装状态和功能的类——你通常不想完全复制它,因为状态可能会随着时间而改变。例如,如果您的应用程序是一个流式视频应用程序,它有一个 VideoPlayer 实例来播放封装在 StreamingVideo 实例中的视频,您不会想要复制 StreamingVideo,因为它的内部状态会随着下载更多数据而不断变化(或发生错误)。

当您想要一个不可变的状态快照时使用Ie copy,当您希望对象 A 连接到 B 以更改/监视/查询 B 的状态时使用引用。

而且,是的,您希望它保持一致。如果一个属性是copy并且您有一个设置该属性的便利初始化程序,请确保该便利初始化程序也复制设置给该属性的任何内容。

于 2012-07-06T20:22:49.177 回答