2013-03-29 102 views
-1

我不明白为什么我必须在Objective-C中执行以下操作。我有兴趣发现为什么在一般意义上(即为什么语言/编译器迫使我这样做),也许发现替代方案,我已经拿出:为什么我的ObjC实现类#import实现协议的_interface_?

我有一个协议:

// (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类中,我需要#导入实现了@protocol的“MyViewController.h”,甚至是尽管具体实现从未在Observed类中明确引用?如果我不这样做,我得到和编译错误:当然,我想有多个不同的视图控制器实现此协议的

no known instance method for selector 'lookAtThisData:' 

这里的问题是,。那么为什么我不得不导入其中的一个来编译它?

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

+1

你能命名包含每个代码段的文件吗?例如“我有一个协议”添加“在foo.h中定义”。 – danh

+0

当然,我做到了。 – scot

+1

错误消息与您发布的代码不匹配。 '-lookAtThisData:'和'-lookAtThisData:withObserver:'是两种不同的方法。否则,您发布的代码是正确的。 '-lookAtThisData:withObserver:'在TheObserved.h中声明,并且这是您需要导入以调用该方法的头。 – Darren

回答

2

您不必导入“MyViewController.h”。

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

而你想要参考方法lookAtThisData:withObserver:的任何地方,你必须导入“TheObserver。H”,因为这是该方法被发表。

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 
1

你举的例子似乎不完整的我,所以我创造了我认为说明了这个问题,在一个自包含的方法的例子。

MyObserver.h :

#import <Foundation/Foundation.h> 

@class TheObserved; 

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

TheObserved.h:

#import <Foundation/Foundation.h> 

@protocol MyObserver; 

@interface TheObserved : NSObject 

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

@end 

TheObserved.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:

No known instance method for selector 'itWasObserved:'

导入MyObserverImple但是,TheObserved.m中的mentation.h修正了这个错误(这与您需要从TheObserved.m导入MyViewController.h类似)。但它只修复错误,因为MyObserverImplementation.h会导入MyObserver.h。 TheObserved.m没有在MyObserver.h中声明的方法的可见性,否则,因为您只是前向声明了协议并且从不导入它。

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

当然,这个答案是根据我的重构你的例子的正确性而预测的。