Общий класс / протокол для UIView / CALayer - вопросы проектирования программного обеспечения - PullRequest
4 голосов
/ 03 марта 2011

У меня очень простой вопрос относительно некоторых решений по разработке программного обеспечения с использованием iOS SDK.

Предположим, у меня есть класс, который управляет представлением объектов вида в моем приложении (UIManager). Этот класс позволяет классам внешних контроллеров добавлять в него объекты представления. Объекты просмотра могут быть двух видов: CALayer и UIView подклассы.

У меня вопрос, какой интерфейс лучше подходит для такого класса 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) Есть ли способ представления классов UIView и CALayer через <MyProtocolType>?

Или, вообще говоря, иметь класс, который обрабатывает эти различные объекты взаимозаменяемо, нехорошо?

Реализация 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> решит ситуацию, однако, как я могу представить оба класса UIView и CALayer в протоколе? Оба класса просто соответствуют <NSObject>.

Заранее спасибо

1 Ответ

1 голос
/ 03 марта 2011

Проверка типа просто необходима. Я думаю, что вопрос можно перефразировать следующим образом: «Я хочу, чтобы менеджер взял либо UIView, либо CALayer и делал с ними разные вещи, но отвергал все остальные». В этом случае проверка типов превосходит хакерство, и я искренне рекомендуем вам просто проверить тип и выдать исключение, когда все идет не так, как ожидалось.

Можно добавить личную категорию, которая действительно, действительно частную, например, категорию с 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;

}
...