chr*_*nes 17 iphone memory-management objective-c
我认为我对objective-c的内存管理有一个很好的处理,但我无法弄清楚以下情况:
@protocol MyProtocol
@end
Run Code Online (Sandbox Code Playgroud)
@interface MyObject : NSObject {
id<MyProtocol> reference;
}
@property (nonatomic, retain) id<MyProtocol> reference;
@end
Run Code Online (Sandbox Code Playgroud)
@implementation MyObject
@synthesize reference;
-(void) dealloc {
[reference release];
[super dealloc];
}
...
@end
Run Code Online (Sandbox Code Playgroud)
这给了我一个" 警告:' - 发布'未在协议中找到 ".我可以安全地忽略这个错误吗?或者我在做一些可怕的错误?
Bar*_*ark 30
是的,您可以安全地忽略此错误.声明为类型的对象id<MyProtocol>可能不继承NSObject(你不具备使用可可库在Objective-C编程还有其他根类甚至在可可等NSProxy).因为retain(和release,autorelease)声明中NSObject,编译器无法知道,声明为类型的实例id<MyProtocol>来响应这些消息.为了解决这个问题,Cocoa还定义了镜像API 的NSObject 协议NSObject.如果您将协议声明为
@protocol MyProtocol <NSObject>
@end
Run Code Online (Sandbox Code Playgroud)
指示MyProtocol扩展NSObject 协议,您将被设置.
Mat*_*her 13
通常,当您声明一个对象时,id它会计算一个"任意"对象(这意味着Objective-C将允许您在id没有警告的情况下从任何类或协议调用任何方法).
但是,当您声明一个对象时id<SomeProtocol>,其含义会发生变化.在这种情况下,您反而说:我只会SomeProtocol在此对象上调用方法.
方法:
- (void)release;
Run Code Online (Sandbox Code Playgroud)
在NSObject协议中声明,但您已明确声明:我只会调用MyProtocol方法.所以编译器会给你一个警告,告诉你你违背了自己的承诺.
因此,而不是:
id<MyProtocol> reference;
Run Code Online (Sandbox Code Playgroud)
你应该真的声明:
id<MyProtocol, NSObject> reference;
Run Code Online (Sandbox Code Playgroud)
要么:
NSObject<MyProtocol> reference;
Run Code Online (Sandbox Code Playgroud)
因为NSObject(类)实现NSObject(协议).
要么:
id reference;
Run Code Online (Sandbox Code Playgroud)
这是最广泛的一部分:让我在这个对象上调用任何东西,永远不要抱怨.
你也可以(巴里Wark的建议)有MyProtocol包括NSObject协议-虽然从设计的角度来看,你通常只能这样做,如果实现MyProtocol一定使用手段NSObject.通常情况下,我们只有做到这一点NSObject,并MyProtocol正在heritarily或语义上的联系.
关于NSObject协议的一些信息:
您调用的所有内容在保留/释放/自动释放时必须实现此协议.正如你可以从中推断的那样:基本上所有东西都实现了NSObject协议(即使有些东西不是从NSObject基类中下来的).
另一个快速澄清:( NSObject类)和NSObject(协议)不是相同API的重新实现.它们分为以下几种:
NSObject(协议)实现了在一般意义上处理/检查现有对象所需的一切(retain/release,isEqual,class,respondsToSelector:等).
NSObject(类)实现了不太通用的方法:构造/销毁,线程集成,脚本集成.
所以在大多数情况下,协议是两者中更重要的.记住这个类包含了协议,所以如果你从NSObject下载,你就得到了这两个协议.