2012-01-27 121 views
8

我在ShareKit中遇到过这样的代码,我不明白作者的想法,在类方法中使用self。有一个警告:不兼容的指针类型将'Class'发送到参数类型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]; 
} 

回答

13

self可以在一个类的方法作为多晶型类实例中使用。

因此,类方法new可以实现这样的:

+ (id)new 
{ 
    return [[self alloc] init]; 
} 

和将返回正确的类型对于被传递消息类实例:

前一个:

NSArray * a = [NSArray new]; // << a is an NSArray 

ex b:

NSMutableArray * a = [NSMutableArray new]; // << a is an NSMutableArray 

请参阅下面的注释。

所以你真正要面对的是确保协议中只有实例方法,并且(类)自己的方法映射出采用协议中的实例方法。

就设计......好吧,我们只是说我不会这样写的。一个单身人士会更清楚,更正确,但我甚至不喜欢单身人士,所以我不会采取这样的路线。

产生此警告是因为类别实例(通过的内容)确实采用delegate参数指定的@protocolClass实例不是该类的一个实例。协议声明确实适用于该类的实例。例如,如果采用NSLocking,编译器是否希望您也为协议中声明的每个实例方法实现类方法?答:从来没有。你正在处理的实施是国际海事组织是这种语言滥用的情况之一,但它恰好运作。

为了阐明术语:

的 “Class实例” 是self在一个类的方法:

+ (void)foo { self; } 

的 “类的实例” 是在实例方法self

- (void)foo { self; } 

实际上,-[NSObject conformsToProtocol:]+[NSObject conformsToProtocol:]+[NSObject class]只是返回self所以执行时没有错误。

我还不清楚,那么,为什么我收到警告,如果代码符合您描述的标准。

我描述的标准适用于执行,但它从语言的语义偏离 - 因此,编译器对这个绝对正确的。

对于解决的问题:有没有办法告诉编译器“我的类的实例符合协议”,因为采用的声明适用于类的实例。

你有两个主要选择:

  1. 干净的,正确的做法:使用类的一个实例和实施所定义的协议。

  2. 或类型转换类实例的协议:

    ID代表=(ID)自我; fbSession = [FBSession sessionForApplication:SHKFacebookKey getSessionProxy:SHKFacebookSessionProxyURL delegate:delegate];

如果选择#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]]; 

(注意的实现这些类型实际上是类集群,并且您将在调试器中看到不同的东西或者如果打印出来)

+0

您的编辑已清除。顺便说一句,该协议只包含实例方法,它们都不涉及接收方。我仍然不清楚,那么,为什么我收到警告,如果代码符合您描述的标准。 – Jim 2012-01-27 04:01:50

+0

@Jim详细添加 – justin 2012-01-27 06:21:14