在过去,我们接受过编写这样的init方法的培训:
foo.h中:
-(id) initWithInteger: (NSInteger) someNumber;
Foo.m:
-(id) initWithInteger: (NSInteger) someNumber {
if ((self = [super init])) {
doSomeStuff;
}
return self;
}
但那些id演员现在已经没有了。那么这些方法现在应该如何看待呢?
编辑:这是一个图书馆。因此,无法确定调用代码的外观。
答案 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。仅作为强制转换表达式的语法无效,因为强制转换本身无效。
添加一个桥接关键字可以满足编译表达式中的编译器,因为那时你告诉它你想要它做什么(没有桥接关键字的跨桥转换是无效的,因为编译器必须猜测你的意思,它拒绝),但在类型声明中是无效的,因为它不是模棱两可的。桥接交叉发生在演员表达(当有一个)时,而不是在参数段落或返回。