2013-03-29 100 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而不是導入視圖控制器來解決問題。

當然,這個答案是根據我的重構你的例子的正確性而預測的。