2012-04-27 87 views
3

我知道我可以使用類來擴展一個類(例如框架類),但是否有可能讓您無法控制源代碼的類實現您的自定義協議之一?我不僅希望在發送給實例時對某些消息作出響應,而且理想情況下還希望在查詢協議時,該類的對象在運行時類型檢查時返回true。是否可以在Objective-C中動態實現協議?

+1

你爲什麼不繼承它並添加該協議? – kuba 2012-04-27 08:28:03

+1

@kuba,因爲我想將它添加到由框架提供的現有實例中,而不僅僅是我實例化自己的實例。 – SoftMemes 2012-04-27 08:35:24

回答

8

可以定義符合協議的範疇,所以你會做這樣的事情:

@interface UIWebView (MyGreatExtensions) <UITableViewDelegate> 
@end 

@implementation UIWebView (MyGreatExtensions) 

- (CGFloat)tableView: (UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath { 
    return 42.0; 
} 

// ... 

@end 

小的邊緣情況下,要考慮的是,如果別人試圖做同樣的事情(例如第三方框架也通過一個類別添加協議),那麼你不能保證你的版本將被使用(當然也不能)。

關於此方法的更多信息from Mark Dalrymple

+0

在這種情況下,最後一個問題並不是真正的問題,因爲我擁有協議本身和實現。這會使UIWebView的現有實例在conformToProtocol for UITableViewDelegate上返回true嗎? – SoftMemes 2012-04-27 09:04:26

+0

是的。實際上並沒有任何「現有實例」,您可以通過將協議的實現添加到該實例來擴充該類。 – 2012-04-27 09:14:20

+0

非常好,謝謝! – SoftMemes 2012-04-27 09:17:37

1

我認爲這是可能的。通過覆蓋NSObject的forwardInvocation:方法,您可以輕鬆地在Objective-C中創建動態代理(這是NSUndoManager的功效),攔截協議實現者將響應的所有未識別消息。我從來沒有這樣做過,所以可能會有更優雅的方式來做到這一點。

此外,欺騙運行時檢查到同意你的對象確實實現了協議,你可以重寫NSObject中的類方法conformsToProtocol:像這樣:

+ (BOOL)conformsToProtocol:(Protocol *)aProtocol { 
    if (aProtocol == @protocol(MyDynamicallyImplementedProtocol)) 
     return YES; 
    return [super conformsToProtocol:aProtocol]; 
} 

有可能是你需要覆蓋更多的方法,一個例子是NSObject的instancesRespondToSelector:和resolve *:方法。檢查NSObject class reference以瞭解更多信息。