【问题标题】:Dynamically typed class generates compiler warnings on method selection动态类型的类在方法选择上生成编译器警告
【发布时间】:2010-02-16 07:08:10
【问题描述】:

也许这是错误的方法,但它似乎是一种干净且可行的方法,我想知道如何才能使编译器警告消失?

@interface SomeView : UIView {
 NSString *stringOfsomeImportance;
 RelatedClass *niftyService;
}
@property (nonatomic, copy) NSString * stringOfnoImportance;
@property (nonatomic, retain) RelatedClass *niftyService;

@implementation
-(void)someMethod;
-(void)otherMethods;

@implementation    RelatedClass *pvSomeObj = [[RelatedClass alloc] initWithSender:self];
[self setNiftyService:pvSomeObj];

现在,看看 RelatedClass 的实现...

@interface RelatedClass : NSObject {
  id  thesender;

@property (nonatomic, retain) id thesender;


@implementation

[thesender otherMethods];  // this generates a compiler warning
                           // that otherMethods cannot be found
                           // in SomeView, though it *is* found
                           // and seems to execute just fine

这似乎是一种有效的方法,所以我想知道为什么会出现警告? 有没有办法更好地向编译器“解释”这一点?

如果鼓励这种类型的链接,或者是否有更好的方法来链接两个需要相互通信的相关、相互依赖的类,有人可以分享一下吗?

我不能在 RelatedClass 中静态声明发送者对象 (SomeView),因为这似乎会导致递归问题,因为 SomeView 是使用 RelatedClass 作为成员定义的...

有什么建议吗?

【问题讨论】:

    标签: objective-c compiler-warnings dynamic-typing


    【解决方案1】:
    1. 您可以定义一个协议并说您的thesender 对象必须符合它:

      @protocol MyProtocol
         -(void)otherMethods;
      @end
      
      @interface RelatedClass : NSObject {
         id<MyProtocol>  thesender; // Now compiler knows that thesender must respond 
                                    // to otherMethods and won't generate warnings
      }
      
    2. 您可以通过其他方式发送otherMethods 消息(您可能需要在此处将theSender 定义为NSObject):

      if ([theSender respondsToSelector:@selector(otherMethods)])
          [theSender performSelector:@selector(otherMethods)];
      
    3. 编辑:实际上,您也可以使用前向类声明在您的相关类中将发件人定义为 SomeView*:

      //SomeView.h
      @class RelatedClass;
      @interface SomeView : UIView {
         RelatedClass *niftyService;
      }
      // then include RelatedClass.h in SomeView.m
      
      //RelatedView.h
      @class SomeView;
      @interface RelatedClass : NSObject {
         SomeView*  thesender;
      }
      // then include SomeView.h in RelatedClass.m
      

    【讨论】:

    • 不过,这实际上并不是问题所在。协议确实解决了问题,但只能先解决真正的问题。
    【解决方案2】:

    在您的标题中,您可以转发声明您想要使用的类。在您的实现文件中,您可以包含您前向声明的那些类的完整标头。

    例如:


    SomeView.h

    #import <FrameworkHeader.h>
    
    // Here, you are saying that there is a class called RelatedClass, but it will be
    // defined later.
    @class RelatedClass;
    
    @interface SomeView : UIView
    {
        RelatedClass *niftyService;
    }
    
    @end
    

    SomeView.m

    #import "SomeView.h"
    #import "RelatedClass.h"
    
    // By including "RelatedClass.h" you have fulfilled the forward declaration.
    
    @implementation SomeView
    // Can use "RelatedClass" methods from within here without warnings.
    @end
    

    RelatedClass.h

    #import <FrameworkHeader.h>
    
    @class SomeView;
    
    @interface RelatedClass
    {
        SomeView *someView;
    }
    // methods
    @end
    

    RelatedClass.m

    #import "RelatedClass.h"
    #import "SomeView.h"
    
    @implementation RelatedClass
    // Can use "SomeView" methods from within here without warnings.
    @end
    

    【讨论】:

      【解决方案3】:
      id  thesender = ....;
      [thesender otherMethods];  // this generates a compiler warning
                                 // that otherMethods cannot be found
                                 // in SomeView, though it *is* found
                                 // and seems to execute just fine
      

      如您所描述的那样产生警告,这完全是因为方法-otherMethods没有在编译器在尝试编译调用站点之前看到声明的地方声明。

      即方法的声明:

      - (void) otherMethods;
      

      必须出现在由编译特定调用站点的实现文件直接或间接导入的头文件中方法声明必须出现在@implementation之前调用站点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多