Objective C类初始化

zhu*_*ber 0 cocoa objective-c

+ (id)packetWithType:(PacketType)packetType
{
    return [[[self class] alloc] initWithType:packetType];
}

- (id)initWithType:(PacketType)packetType
{
    if ((self = [super init]))
    {
        // code
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

为什么我们需要第一类方法,不是第二个就足够初始化了?

Dir*_*irk 6

有方便的构造函数类方法有两个原因.第一个是,成语[[Thing alloc] initWithFoo: xyz]很常见,但不方便在任何地方打字.所以,[Thing thingWithFoo: xzy]是一个常见的缩写.

更深层次的原因与引用计数有关.以#开头的方法init应该返回实例的引用,其所有权转移给调用者.方便类方法通常返回autoreleased引用:

+ (id)packetWithType:(PacketType)packetType
{
    return [[[[self class] alloc] initWithType:packetType] autorelease];
}
Run Code Online (Sandbox Code Playgroud)

知道这一点很重要,以避免悬空引用和/或内存泄漏:

Thing* thing = [[Thing alloc] initWithFoo: xyz];
// Now, *I* own the reference and *I* am responsible for releasing
// it, when I no longer need it.
[thing release]
Run Code Online (Sandbox Code Playgroud)

另一方面,返回的引用

Thing* thing = [Thing thingWithFoo: xyz];
Run Code Online (Sandbox Code Playgroud)

由"最近的"拥有NSAutoreleasePool.调用者不负责释放它(事实上,这是错误的!).如果要保留引用,则调用者必须retain在此处实际显示:

self->myMember = [thing retain];
Run Code Online (Sandbox Code Playgroud)

即使使用ARC,您也应该了解这些约定,因为基础规则仍然有效,即使(在ARC下)它是编译器,它生成代码来遵守它们.的NARC缩写,是一个很好的方式来记住,该方法的名称前缀配备一定的责任.这个答案有详细说明.