iOS - arc下的initWith方法

时间:2011-07-29 12:57:19

标签: iphone objective-c ios automatic-ref-counting

在过去,我们接受过编写这样的init方法的培训:

foo.h中:

-(id) initWithInteger: (NSInteger) someNumber;

Foo.m:

-(id) initWithInteger: (NSInteger) someNumber {
    if ((self = [super init])) { 
       doSomeStuff;
    }
    return self;
 }

但那些id演员现在已经没有了。那么这些方法现在应该如何看待呢?

编辑:这是一个图书馆。因此,无法确定调用代码的外观。

3 个答案:

答案 0 :(得分:8)

为什么你说回归id是禁忌? ARC specification

  

init方法必须是实例方法,并且必须返回Objective-C指针类型。另外,如果程序声明或包含对init方法的调用,该方法的返回类型既不是id也不是指向声明类的超类或子类的指针(如果方法是在类上声明的) )或调用的静态接收器类型(如果它是在协议上声明的那样)。

此外,请记住,使用ARC是每个文件的决定,即使用ARC编译的代码可以与没有ARC的代码一起使用,反之亦然。对于库的头文件,您应该准备它以便可以在两者上使用它,但是为非ARC情况做好准备就足够了。

答案 1 :(得分:4)

这就是我现在所做的事情:

-(id) initWithInteger: (NSInteger) someNumber {
    self = [super init];
    if (self) { 
       doSomeStuff;
    }
    return self;
}

它会使警告消失,它在逻辑上是等同的,虽然不是那么优雅。

Duh,我现在感觉自己像个傻瓜,并没有阅读这个问题来理解它。但是我发现这个link指向可能有所帮助的东西。具体来说,它在第5节中说明:

  

init方法必须是实例方法,并且必须返回Objective-C指针类型。另外,如果程序声明或包含对init方法的调用,该方法的返回类型既不是id也不是指向声明类的超类或子类的指针(如果方法是在类上声明的) )或调用的静态接收器类型(如果它是在协议上声明的那样)。

基于此,看起来你不需要做任何事情,这是有道理的。甚至Apple对开发者来说都是残酷的。你收到编译错误了吗?我还没有跳到狮子座,所以我还没有看到ARC。

答案 2 :(得分:0)

  

在过去,我们接受过编写这样的init方法的培训:

     

foo.h中:

-(id) initWithInteger: (NSInteger) someNumber;
     

Foo.m:

-(id) initWithInteger: (NSInteger) someNumber {
   if ((self = [super init])) { 
      doSomeStuff;
   }
   return self;
}
     

但那些id演员现在已经没有了。那么这些方法现在应该如何看待呢?

那些不是演员表。在该上下文中,简单的语法声明方法的返回类型,因为稍后(NSInteger)部分声明该参数的类型。

声明方法返回类型的语法在ARC下没有改变。您展示的代码将保持完全相同。

强制转换是表达式,因此ARC禁止的类型转换只能出现在表达式上下文中。例如,如果你说:

- (id) initWithCFThing:(CFThingRef)thing {
    if ((self = [super init])) {
        _thing = (NSThing *)thing; //Casts expression of type CFThingRef to object pointer type NSThing *; this is invalid
    }
    return self;
 }

赋值表达式中的强制转换无效,因为它从CF对象转换为没有桥关键字的Objective-C对象指针(“可保留对象指针”)。反向同样是无效的:

- (CFThingRef) CFThing {
    return _thing; //Implicitly casts expression of object pointer type NSThing *to type CFThingRef; this is invalid
}

另一个方向的相同问题:赋予return语句的表达式将可保留对象指针强制转换为没有桥关键字的CF对象类型。

注意错误所在。在每种情况下,错误都在表达式中:在initWithCFThing:中,它是赋值表达式中的显式cast-expression;在访问器CFThing中,它是return语句中表达式对方法返回类型的隐式转换。

在这两种情况下,与您的情况一样,该方法的原型完全有效。当您声明方法的返回类型或参数类型时,(CFThingRef)(id)仍然有效,无论是否有ARC。仅作为强制转换表达式的语法无效,因为强制转换本身无效。

添加一个桥接关键字可以满足编译表达式中的编译器,因为那时你告诉它你想要它做什么(没有桥接关键字的跨桥转换是无效的,因为编译器必须猜测你的意思,它拒绝),但在类型声明中是无效的,因为它不是模棱两可的。桥接交叉发生在演员表达(当有一个)时,而不是在参数段落或返回。