我在ShareKit中遇到过这段代码,在类方法中使用self
时,我不明白作者的想法。有一个警告:不兼容的指针类型发送&#39; Class&#39;到参数类型id<FBSessionDelegate>
。 我想清理这些警告,所以我可以看到后来可能受到伤害的警告。我能做什么/应该做什么不会打破这个?
这是SHKFacebook.m文件,类名是SHKFacebook
+ (void)logout
{
FBSession *fbSession;
if(!SHKFacebookUseSessionProxy){
fbSession = [FBSession sessionForApplication:SHKFacebookKey
secret:SHKFacebookSecret
delegate:self];
}else {
fbSession = [FBSession sessionForApplication:SHKFacebookKey
getSessionProxy:SHKFacebookSessionProxyURL
delegate:self];
}
[fbSession logout];
}
答案 0 :(得分:14)
self
可以在类方法中用作多态类实例。
因此,类方法new
可以像这样实现:
+ (id)new
{
return [[self alloc] init];
}
并将返回消息的Class实例的正确类型:
ex a:
NSArray * a = [NSArray new]; // << a is an NSArray
ex b:
NSMutableArray * a = [NSMutableArray new]; // << a is an NSMutableArray
见下面的注释。
所以你真正面临的是确保协议中只有实例方法,并且(Class)自我方法映射出来采用协议中的实例方法。
就设计而言......好吧,我只想说我不会这样写。单身人士会更清楚,更正确,但我不喜欢单身人士,所以我不会采取这种方式。
产生警告是因为 Class 实例(传递的内容)确实采用@protocol
参数指定的delegate
。 Class
实例不是该类的实例。协议声明确实适用于该类的实例。例如,如果采用NSLocking
,编译器是否期望您还为协议中声明的每个实例方法实现类方法?答:永远不会。您正在处理的实施是IMO其中一种滥用该语言的情况,但它恰好起作用。
澄清术语:
&#34; Class
实例&#34;在类方法中是self
:
+ (void)foo { self; }
&#34;班级的实例&#34;在实例方法中是self
:
- (void)foo { self; }
实际上,-[NSObject conformsToProtocol:]
为+[NSObject conformsToProtocol:]
而+[NSObject class]
只返回self
,因此执行时没有错误。
我还不清楚,如果代码符合您所描述的标准,为什么我会收到警告。
我描述的标准适用于执行,但它偏离了语言的语义 - 因此,编译器在这方面绝对正确。
要解决问题:没有办法告诉编译器&#34;我的类实例符合协议&#34;因为采用声明适用于类的实例。
您有两个主要选项:
干净,正确的方法:使用类的实例并实现定义的协议。
或者对协议的类实例进行Typecast:
id delegate =(id)self; fbSession = [FBSession sessionForApplication:SHKFacebookKey getSessionProxy:SHKFacebookSessionProxyURL 委托:委托];
如果选择#2,则可以帮助定义协议的实例方法以使用类方法,如下所示:
+ (void)protocolMethod { /* do stuff */ }
- (void)protocolMethod { [self.class protocolMethod]; }
这也意味着你永远不需要实例。它会有所帮助,因为如果协议发生变化,它会添加警告。当你遵循惯例时,这些警告会冒泡到类方法。
为了减少噪音,您还可以考虑创建一些方法来将类型转换减少到一个位置:
+ (id<SomeProtocol>)sharedSomeProtocolDelegate
{
return (id<SomeProtocol>)self;
}
- (id<SomeProtocol>)sharedSomeProtocolDelegate
{
return [[self class] sharedSomeProtocolDelegate];
}
然后你可以写:
fbSession = [FBSession sessionForApplication:SHKFacebookKey
getSessionProxy:SHKFacebookSessionProxyURL
delegate:[self sharedSomeProtocolDelegate]];
(请注意,这些类型的实现实际上是类集群,您将在调试器中看到不同的内容或打印出来的内容)