2011-03-03 57 views
4

對於使用iOS SDK的一些軟件設計決策,我有一個非常簡單的問題。UIView/CALayer的通用類/協議 - 軟件設計問題

假設我有一個類管理我的應用程序中的視圖對象的表示(UIManager)。該類允許外部控制器類向其添加視圖對象。視圖對象可以有兩種:CALayerUIView子類。

我的問題是哪個接口更適合這樣的UIManager類。 例如:

@interface UIManager : UIView {} 

// 1) 
- (void)addGenericViewObject:(id)genericViewObject; 

// 2) 
- (void)addUIViewObject:(UIView*)uiViewObject; 
- (void)addCALayerObject:(CALayer*)caLayerObject; 

// 3) 
- (void)addMyProtocolTypeViewObject(id<MyProtocolType>)myProtocolTypeViewObject; 
@end 

1)id類型太普通?

2)每種類型都有不同的方法簽名會導致代碼重複?

3)有沒有辦法通過<MyProtocolType>來代表UIViewCALayer類?

或者更一般地說,有處理這些不同對象的類可以互換不好嗎?

UIManager的實施將是這樣的:

@implementation UIManager 

// 1) 
- (void)addGenericViewObject:(id)genericViewObject { 
    if ([genericViewObject isKindOfClass:[UIView class]]) { 
     [_uiViewsContainer addSubview:(UIView*)genericViewObject]; 
    } else if ([genericViewObject isKindOfClass:[CALayer class]]) { 
     [_caLayersContainer addSublayer:(CALayer*)genericViewObject]; 
    } 
} 
@end 

類型檢查總是不好的,也許有<MyProtocolType>但會解決的情況下,怎麼可能我代表協議雙方UIViewCALayer類?這兩個類只符合<NSObject>

在此先感謝

+0

奈斯利提出的問題:) – xyz 2011-03-03 16:02:03

回答

1

類型檢查是如此必要。我認爲有可能重構這個問題......「我想要一個經理接受一個UIView或一個CALayer,並對他們做不同的事情,但拒絕所有其他事情。」在這種情況下,類型檢查勝過hackery,而我全心全意地建議你只需要進行類型檢查,並在事情沒有按預期進行時拋出異常。

可以添加一個真正私有的類別,例如一個帶有64個字符的隨機標識符的私有類別給CALayer和UIView,它們將這些類符合到一個自定義協議,並且只檢查符合性。但是這種類型檢查確實起作用,並且是非常多的(不必要的)工作。上次我嘗試了,GCC似乎討厭這個。

我覺得這可能是工作,假如以後你正在處理大量的類:

- (BOOL) addInterfaceObject:(id)anObject { 

    void (^handler)(); 

    if (!(handler = [self interfaceObjectHandlerForClass:[anObject class]])) 
    return NO; // Or throw an exception 

    handler(anObject); 
    return YES; 

} 

- (void(^)(id anObject)) interfaceObjectHandlerForClass:(Class)aClass { 

// Or retrieve copy-autoreleased blocks from a dictionary 

    if ([aClass isSubclassOfClass:[UIView class]]) 
    return^(id anObject) { [self.view addSubview:(UIView *)anObject]; }; 

    if ([aClass isSubclassOfClass:[CALayer class]]) 
    return^(id anObject) { [self.view.layer addSublayer:(CALayer *)anObject]; }; 

    return nil; 

} 
+0

所以,對於'UIManager'類接口的解決方案是1),其意味着'addGenericViewObject:'參數不可避免地被推廣到'id'。在'UIManager'類中使用塊/異常看起來是處理'id'通用性的好方法。解決方案2)絕對是最差的。解決方案3)是我正在尋找的:一種代表UIView和CALayer的協議,並允許'UIManager'類通過這種協議而不是'id'爲方法參數定義特定的合約。 – 2011-03-03 19:53:03

+0

我認爲協議可以工作,但我個人反對。;) – 2011-03-04 01:57:24

+0

通過將你的代碼片段複製並粘貼到我的'UIManager'類(一個UIView子類)中,我得到了以下錯誤:「在本地堆棧上存在的返回塊」,返回如下代碼:'return ^(id anObject){ [self addSubview:(UIView *)anObject]; };''和'return ^(id anObject){[self.layer addSublayer:(CALayer *)anObject]; };'。看起來像我不能從那個角度正確訪問'self'有什麼問題? – 2011-03-08 20:26:31