【问题标题】:Common class/protocol for UIView/CALayer - software design issuesUIView/CALayer 的通用类/协议 - 软件设计问题
【发布时间】:2011-03-03 15:15:49
【问题描述】:

关于使用 iOS SDK 的一些软件设计决策,我有一个非常简单的问题。

假设我有一个类来管理我的应用程序中视图对象的呈现 (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) 有没有办法通过&lt;MyProtocolType&gt; 表示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

类型检查总是很糟糕,也许拥有&lt;MyProtocolType&gt; 可以解决这种情况,但是,我如何在协议中同时表示UIViewCALayer 类?这两个类都符合&lt;NSObject&gt;

提前致谢

【问题讨论】:

    标签: iphone uiview protocols class-design calayer


    【解决方案1】:

    类型检查是非常必要的。我认为可以将问题重新定义为……“我希望经理采用 UIView 或 CALayer 并对它们做不同的事情,但拒绝所有其他事情。”在这种情况下,类型检查胜过骇客,我全心全意地建议您只进行类型检查,并在事情不按预期进行时抛出异常。

    可以向 CALayer 和 UIView 添加一个真正非常私有的私有类别,例如具有 64 个字符的随机标识符的类别,这使这些类符合自定义协议,并且只需检查一致性。但这就是类型检查所做的,并且是大量(不必要的)工作;上次我尝试时,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;
    
    }
    

    【讨论】:

    • 所以,UIManager 类接口的解决方案是 1),这意味着addGenericViewObject: 参数应该不可避免地推广到id。在UIManager 类中使用块/异常似乎是处理id 通用性的好方法。解决方案2)绝对是最糟糕的。解决方案 3) 是我一直在寻找的:一个同时代表 UIView 和 CALayer 的协议,并允许 UIManager 类通过此类协议而不是 id 为方法参数定义特定协定。
    • 我认为协议可以工作,但我个人反对。 ;)
    • 通过将代码 sn-p 复制并粘贴到我的 UIManager 类(UIView 子类)中,我收到以下错误:“返回位于本地堆栈上的块”,如下行:@ 987654330@ 和return ^ (id anObject) { [self.layer addSublayer:(CALayer *)anObject]; };。看起来我无法从那时起正确访问 self 有什么问题?
    • 哦,当然是疏忽了。请返回 [[^ {} copy] autorelease] 以便它从堆栈到堆 (?) 并且可以在堆栈外使用。
    猜你喜欢
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 2015-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多