澄清对于客观c对象的一般自定义init方法/指针

时间:2012-03-29 02:24:16

标签: objective-c pointers initialization

当我拥有自己的具有合成属性的init方法时:

@property (copy, nonatomic)   NSString       *bookName;
@property (strong, nonatomic) NSMutableArray *book;

当我想用我自己的自定义初始化程序进行初始化时,我会看到这样写:

-(id) initWithName: (NSString *)name
{
    self = [super init]
    if (self) {
        bookName = [NSString stringWithString: name];
        book     = [NSMutableArray array];
    }
    return self;
}

现在我想澄清一些事情。我知道为什么它使用stringWithString方法,因为它不是仅仅将地址传递给传入的字符串,而是创建一个新对象,以便它拥有字符串本身。难道我也不能这样写:

self.bookName = name;

这样做应该使用合成方法并实际创建一个新对象吗?基本上两者都完成了同样的事情。我问,因为有其他方法显示两种方式,所以我只是想确保没有其他问题可以使用这种或那种方式突然出现。它们似乎都以不同的方式做同样的事情(使用合成方法与直接修改类变量但在内存中为它创建一个新对象)。

我还要指出这是在ARC环境中。

3 个答案:

答案 0 :(得分:4)

(请注意,我假设上面是ARC代码;否则它是不正确的。)

您几乎应该始终使用访问者来访问您的ivars(即使在ARC中)。但是,关于init是否应该使用访问者或直接访问其ivars存在一些争议。我在这场争论中已经改变了立场,但IMO并不是一个明显的决定。

不允许init使用访问器的主要参数是未来(未知)子类可能会在访问器中创建副作用。您通常不希望在init期间发生副作用。例如,当您将某些内容设置为其初始值时,您可能不希望发布更改通知,并且您的对象可能处于“未定义状态”,此时此类读取将很危险。

尽管如此,虽然这个论点最终影响了我,但我从未在多个团队的各种规模的项目中遇到过这种情况。我曾经多次遇到开发人员在retain中设置他们的ivars时失败init(如上所述,如果不是ARC则会崩溃)。这就是为什么很长一段时间我甚至在init中建议使用访问器。但理论上它确实会带来危险,特别是如果你是一个闭源框架作家(即Apple)。因此,对于我自己的代码,我现在避免init中的访问者。如果我在较早的保留/释放代码上与更年轻的团队合作,我可能仍会让他们在init中使用访问者。根据我的经验,它只是避免了这么多崩溃。

但是,您应该避免在dealloc中调用访问者,这一点没有争议。这肯定会在摧毁你的物体的过程中导致奇怪的副作用。

答案 1 :(得分:1)

你是对的,因为bookName被声明为copy,分配self.bookName会传入传入的字符串的副本。我不确定复制将通过与[NSString stringWithString: name]完全相同的代码路径,但它将实现创建原始字符串副本的相同目的,使您免受用户传入可变对象的意外后果并改变其后面的值你的背。

答案 2 :(得分:1)

因为声明的属性是copy然后是,所以他们正在做同样的事情。

然而,很多时候它是strong,然后两种方法之间会有区别,所以第一种方法就是“正确”的方法。