开发者

Common class/protocol for UIView/CALayer - software design issues

I have a very simple question regarding some software design decisions using the iOS SDK.

Suppose I have a class that manages the presentation of view objects in my application (UIManager). This class allows external controller classes to add view objects to it. The view objects can be of two kinds: CALayer and UIView subclasses.

My question is which interface is more well suited for such UIManager class. For instance:

@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) The id type is too generic?

2) Having a different method signature for each type can lead to awful code duplication?

3) Is there a way to represent both UIView and CALayer class through <My开发者_StackOverflowProtocolType> ?

Or more generally speaking, having class that handle these different objects interchangeable is not good?

The implementation of UIManager would be something like this:

@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

Type checking is always bad, maybe having <MyProtocolType> would solve the situation, however, how could I represent both UIView and CALayer class in a protocol? Both classes just conform to <NSObject>.

Thanks in advance


Type checking is just so necessary. I think that it is possible to reframe the question to… “I want a manager to take either an UIView or a CALayer and do different things to them, but reject all the other things.” In that case, type checking trumps hackery and I wholeheartedly recommend that you just type-check, and throw an exception when things do not go as expected.

It is possible to add a private category that is really, really private, like one with a 64-character random identifier, to both CALayer and UIView, which conforms the classes to a custom protocol, and just check for conformity. But that does what type-checking does, and is an awful lot of (unnecessary) work; last time I tried, GCC appears to hate that.

I think this could work, if later on you are dealing with lots of classes:

- (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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜