【问题标题】:First time using Protocols - Objective-C第一次使用协议 - Objective-C
【发布时间】:2011-06-05 09:44:30
【问题描述】:

这是我第一次在 Objective-C 中使用协议,我遇到了麻烦:这就是我所拥有的:

我有一个 ReportsReceiver.h:

@protocol ReportsReceiver


-(void)receiveData:(NSArray *)theData;

@end

我有一个 MyController.h:

@interface MyController : UIViewController<ReportsReceiver,UITableViewDelegate,UITableViewDataSource> {

}
@end

我有一个带有已实现方法的 MyController.m:

- (void)receiveData:(NSArray *)theData {
    NSLog(@"received some data!");
}

然后我有一个带有声明的类 AllUtilities.m:

Protocol *receiverProtocol;

AllUtilities.m 还包含一个初始化协议的方法:

- (void)initProtocol {
    receiverProtocol = @protocol(ReportsReceiver);

}

然后在 AllUtilities.m 中我拨打电话:

[receiverProtocol receiveData:anArray];

哪个应用程序因错误而崩溃:

2011-01-07 11:46:27.503 TestGA[91156:207] *** NSInvocation: warning: object 0x9c28c of class 'Protocol' does not implement methodSignatureForSelector: -- trouble ahead
2011-01-07 11:46:27.504 TestGA[91156:207] *** NSInvocation: warning: object 0x9c28c of class 'Protocol' does not implement doesNotRecognizeSelector: -- abort

我该如何解决这个问题?谢谢!!

【问题讨论】:

    标签: iphone ios methods protocols


    【解决方案1】:

    您应该再次阅读Objective-C guide 中有关协议的部分 :) 我认为您并不真正了解协议的工作原理。这就是你想要的:

    // DataProducer.h
    @protocol DataConsumer
    - (void) handleData: (NSArray*) data;
    @end
    
    @interface DataProducer
    @end
    
    // DataProducer.m
    @implementation DataProducer
    
    - (void) generateDataAndPassTo: (id <DataConsumer>) consumer
    {
         NSArray *data = …;
         [consumer handleData:data];
    }
    
    // SomeController.h
    #import "DataProducer.h"
    
    @interface SomeController <DataConsumer>
    @end
    
    // SomeController.m
    @implementation SomeController
    
    - (void) requestData
    {
        // The producer is of type DataProducer.
        // Where you get it is irrelevant here.
        [producer generateDataAndPassTo:self];
    }
    
    - (void) handleData: (NSArray*) data
    {
        NSLog(@"Got data.");
    }
    
    @end
    

    【讨论】:

      【解决方案2】:

      协议本质上是一个约定,例如,“符合ReportsReceiver 协议的对象必须实现receiveData: 方法”。

      因此,MyController.h 承诺 receiveData: 将出现,而 MyController.m 履行了承诺。到目前为止一切顺利。

      现在,您的receiver 变量并不关心接收者究竟是什么类型的对象,只要它符合ReportsReceiver 协议即可。你声明的方式是:

      id<ReportsReceiver> receiver;
      

      ...在你的初始化中你可能会说:

      receiver = myController;
      

      然后像这样调用它:

      [receiver receiveData:anArray];
      

      【讨论】:

      • 你是什么意思“在你的初始化”? myController 到底是什么?
      【解决方案3】:

      首先将 NSObject 协议添加到您自己的协议中。您收到的警告是来自 NSObject 的方法。

      @protocol ReportsReceiver <NSObject>
      
      -(void)receiveData:(NSArray *)theData;
      
      @end
      

      在声明实现协议的对象时,应该更像:

      id<ReportsReceiver> receiverProtocol;
      

      ReceiverClass<ReportsReceiver> *receiverProtocol;
      

      如果您创建了一个实现 ReportsReceiver 协议的对象 (ReceiverClass)。

      您分配一个实现协议的类的方式与分配任何其他类的方式相同:

      ReceiverClass<ReportsReceiver> *receiverProtocol;
      - (void)initProtocol {
          receiverProtocol = [[ReceiverClass alloc]init];
      }
      

      @protocol 指令开始声明一个协议,而不是强制转换为一个。查看docs 了解如何使用它们。

      【讨论】:

      • 不需要将 NSObject 添加到协议中;他之所以收到这些错误,是因为他试图调用一个没有用的“协议”对象。
      • 所以在我的 AllUtilities 中,我必须为我想要实现该协议的每个类声明一个协议?我不明白。
      • 不,你定义了一次协议。然后在您想要的任何类上实现该协议。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-10
      • 2014-12-15
      • 1970-01-01
      • 2011-06-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多