【问题标题】:Using @class to get access to a delegate protocol declaration使用@class 访问委托协议声明
【发布时间】:2013-10-21 16:25:11
【问题描述】:

我读到您应该尝试在头文件中使用@class 而不是#import,但是当您的@class 包含您尝试使用的委托协议时,这不起作用。

MyView.h

#import <UIKit/UIKit.h>
@class MyCustomClass;  // <-- doesn't work for MyCustomClassDelegate, used below

@interface MyView : UIView <MyCustomClassDelegate>

@end

我想我忽略了一些东西,有没有办法让@class 在这种情况下工作,或者#import 是我唯一的选择?

编辑:一种解决方法当然是在 .m 文件而不是 .h 文件的私有接口部分声明您的#import MyCustomClass 和 MyCustomClassDelegate。

【问题讨论】:

    标签: objective-c import header-files forward-declaration objective-c-protocol


    【解决方案1】:

    如果您只需要这样的变量,您可以使用@protocol 转发声明协议:

    @protocol MyProtocol;
    
    @interface MyClass {
        id<MyProtocol> var;
    }
    @end
    

    在您的情况下,声明的类试图符合协议,因此编译器此时必须知道协议方法,以便推断天气或类不符合。

    在这种情况下,我认为您的选择是将协议拆分为它自己的文件和 #import 该标头,或者在使用它的类声明上方的该标头中声明该协议。

    【讨论】:

      【解决方案2】:

      您只能在同一个头文件中前向声明一个协议,以便在方法返回值或参数类型中使用。在您的情况下,您希望该类符合协议,因此它不起作用,因为它定义了将添加到类本身的行为(即它将响应的方法)。

      因此,您必须#import 协议。出于这个原因,将协议和类拆分为单独的文件可能是一个好主意。请参阅this answer 了解更多信息。

      【讨论】:

      • 不是为了刻薄,而是更准确地说:您可以前向声明一个协议,但如果您声明一个符合该协议的类(在该头文件中),则不能。如果该协议仅用于方法返回或参数类型,则可以声明它(并且您使用“@protocol MyProtocol;”而不是“@class MyProtocol;”来这样做)。
      【解决方案3】:

      MyCustomClassDelegate 是一个协议,而不是一个类。告诉编译器MyCustomClass 的存在不会告诉它协议的存在。

      【讨论】:

        【解决方案4】:

        你需要在上课前声明你的委托协议:

        MyCustomClass.h:

        #import <UIKit/UIKit.h>
        @class MyCustomClass;
        
        @protocol MyCustomClassDelegate <NSObject>
        
        - (void)myCustomClass:(MyCustomClass *)customClass
                      didBlah:(BOOL)blah;
        
        @end
        
        @interface MyCustomClass : NSObject <MyCustomClassDelegate>
        
        @end
        

        你甚至不能使用@protocol 来转发声明委托协议;编译器必须看到完整的声明,因此将您的 @class 更改为 #import

        MyView.h:

        #import <UIKit/UIKit.h>
        #import "MyCustomClass.h"    // the compile now knows what MyCustomClassDelegate is
        
        @interface MyView : UIView <MyCustomClassDelegate>
        
        @end
        

        【讨论】:

        • 嗯?我认为他的意思是协议已经在他引用的类中声明,因此不需要再次声明。
        • @Bot 啊,是的,他只需要使用#import 而不是@class。我的错。
        【解决方案5】:

        您不能转发声明您遵守的协议。

        如果您仅在MyView 的实现中使用MyView 作为MyCustomClassDelegate,则可以在MyView 的.m 文件中使用Extension,例如:

        #import "MyView.h"
        #import "MyCustomClassDelegate.h"
        
        @interface MyView () <MyCustomClassDelegate> {
        
        }
        
        @end
        
        @implementation MyView
            ...
        @end
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-27
          • 1970-01-01
          相关资源
          最近更新 更多