-1

我不明白为什么我必须在 Objective-C 中执行以下操作。我有兴趣发现一般意义上的原因(即为什么语言/编译器强迫我这样做),并且可能会发现我提出的实现的替代方案:

我有一个协议:

// (file: MyObserver.h)
@class TheObserved;
@protocol MyObserver <NSObject>
   - (void)itWasObserved:(TheObserved *)observedInstance;
@end

有一个接口“TheObserved”(循环地)使用该协议:

// (file: TheObserved.h)
@protocol MyObserver;
@interface TheObserved : NSObject
   @property id <MyObserver> myObserver;
   - (void)lookAtThisData:(NSString *)someData withObserver:(id <MyObserver>)observer;
@end

也就是说,正如你所看到的,协议有一个消息,它接受一个接口的实例,而接口有一个方法,它接受一个实现协议的实例。

在我的接口实现中:

// (file: TheObserved.m)
#import "TheObserved.h"
#import "MyViewController.h" // <-- note this import
@implementation TheObserved
    @synthesize myObserver;

    - (void)lookAtThisData:(NSString *)someData withObserver:(id <MyObserver>)observer {
        self.myObserver = observer;
        // some asynchronous looking at the data is done here.
    }

    - (void)asynchCallback:(NSData *) data {
        // check if the data is as we expect, if so ..
        [self.myObserver itWasObserver: self]
    }
@end

MyViewController.h 实现协议:

// (file: MyViewController.h)
#import <UIKit/UIKit.h>
#import "OWLMorphDataObserver.h"
@interface MyViewController : UITableViewController <MyObserver>
@end

并在其实施中:

// (file: MyViewController.m)
#import "TheObserved.h"
@interface MyViewController () {
  @property TheObserved *observed;
@end

@implementation MyViewController
   @synthesize observed;
   - (void) aMethod:(NSString *)dataString {
       [self.observed lookAtThisData:dataString withObserver:self]
   }
@end

我的问题是:为什么在我的 Observed 类中,我需要 #import 实现 @protocol 的“MyViewController.h”,即使具体实现从未在 Observed 类中显式引用?如果我不这样做,我会得到编译错误:

no known instance method for selector 'lookAtThisData:'

这里的问题当然是我想让多个不同的视图控制器实现这个协议。那么为什么我要强制导入其中一个来编译呢?

是否有另一种方法可以构造此代码以获得所需的效果,而无需在要使用它的类中导入协议的具体实现?

4

3 回答 3

2

您不必导入“MyViewController.h”。

您必须导入“MyObserver.h”。否则,将不知道 MyObserver 协议。任何要引用协议 MyObserver 的地方,都必须导入定义协议的文件。该文件是“MyObserver.h”。

并且任何你想引用方法的地方lookAtThisData:withObserver:,你都必须导入“TheObserver.h”,因为那是发布该方法的地方。

于 2013-03-29T01:45:10.530 回答
1

抱歉,我很难按照您提供的示例进行操作。我使用这种模式不需要任何额外的包含......

一个类定义了一个其他人将实现的协议......

//  Foo.h

@protocol FooDelegate;  // promise to define protocol, so we can refer to it in @interface

@interface Foo : NSObject
@property(nonatomic, weak) id<FooDelegate> delegate;
@end

// now define the protocol
@protocol FooDelegate <NSObject>
- (CGFloat)getFloatForFoo:(Foo *)aFoo;
@end

实现可以调用协议,知道委托实现它......

// Foo.m

#import "Foo.h"

- (void)anyFooMethod {
    CGFloat aFloatFromMyDelegate = [self.delegate getFloatForFoo:self];
}

另一个类将自己声明为协议的实现者(公开或私下,但私下通常是正确的)。

// OtherClass.m

#import "Foo.h"  // notice only one, intuitive import

@interface OtherClass <FooDelegate>
@end

@implementation OtherClass

- (id)init {

    // normal init jazz
    Foo *aFoo = [[Foo alloc] init];
    aFoo.delegate = self;
}

@end
于 2013-03-29T01:40:13.773 回答
1

您的示例对我来说似乎不完整,因此我创建了一个示例,我认为以自包含的方式说明了问题。

MyObserver.h:

#import <Foundation/Foundation.h>

@class TheObserved;

@protocol MyObserver <NSObject>
- (void)itWasObserved:(TheObserved *)observedInstance;
@end

观察到的.h:

#import <Foundation/Foundation.h>

@protocol MyObserver;

@interface TheObserved : NSObject

@property id <MyObserver> myObserver;
- (void)lookAtThisData:(NSString *)someData withObserver:(id <MyObserver>)observer;

@end

观察到的.m:

#import "TheObserved.h"

@implementation TheObserved
@synthesize myObserver;

- (void)lookAtThisData:(NSString *)someData withObserver:(id <MyObserver>)observer {
    self.myObserver = observer;
    // some asynchronous looking at the data is done here.
}

- (void)asynchCallback:(NSData *) data {
    // check if the data is as we expect, if so ..
    [self.myObserver itWasObserved: self];
}
@end

MyObserverImplementation.h:(在您的示例中这是 MyViewController.h)

#import <Foundation/Foundation.h>
#import "MyObserver.h"

@interface MyObserverImplementation : NSObject <MyObserver>

@end

MyObserverImplementation.m:

#import "MyObserverImplementation.h"
#import "TheObserved.h"

@interface MyObserverImplementation ()
@property TheObserved *observed;
@end

@implementation MyObserverImplementation

- (void) aMethod:(NSString *)dataString {
    [self.observed lookAtThisData:dataString withObserver:self];
}

@end

由于 TheObserved.h 中的错误,此程序无法构建:

选择器“itWasObserved:”没有已知的实例方法

但是,从 TheObserved.m 导入 MyObserverImplementation.h 确实可以修复此错误(这类似于您需要从 TheObserved.m 导入 MyViewController.h)。但它只修复了错误,因为 MyObserverImplementation.h 导入了 MyObserver.h。TheObserved.m 对 MyObserver.h 中声明的方法没有可见性,否则,因为您只前向声明了协议而从未导入它。

您可以通过直接从 TheObserved.m 中导入 MyObserver.h 而不是导入视图控制器来解决此问题。

当然,这个答案是基于我重建你的例子的正确性。

于 2013-03-29T01:48:23.453 回答