Выделить или инициализировать подкласс из суперкласса - PullRequest
1 голос
/ 23 апреля 2011

У меня есть универсальное приложение для iOS, над которым я работаю. По большей части я обрабатывал различия между устройствами, создавая подклассы, поэтому RootViewController разделен на подклассы RootViewController-iPad и RootViewController-iPhone. Шаблон начинается в main.m, где я делаю обнаружение устройства следующим образом:

int retVal;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
    retVal = UIApplicationMain(argc, argv, nil, @"SalesPadAppDelegate_iPad");
} else {
    retVal = UIApplicationMain(argc, argv, nil, @"SalesPadAppDelegate_iPhone");
}

Этот шаблон работает довольно хорошо и сводит к минимуму повторное использование кода.

Далее по стеку у меня есть серия контроллеров представления, которые наследуются от общего суперкласса, MasterDetailViewController. Этот суперкласс нуждается в некотором коде, специфичном для устройства, поэтому я подумал о том, чтобы создать подкласс этого класса, а затем получить суперкласс, автоматически выделяющий или создающий экземпляр специфичного для устройства подкласса, который наиболее подходит.

Реализация мудрая, это выглядит следующим образом:

+(id)allocWithZone:(NSZone *)zone {
    if ([[self class] isEqual:[MasterDetailViewController_iPad class]] || [[self class] isEqual:[MasterDetailViewController_iPhone class]]) {
        return [super allocWithZone:zone];
    } else {
        if ([[UIDevice currentDevice] userInterfaceIdiom]==UIUserInterfaceIdiomPhone) {
            return [MasterDetailViewController_iPhone allocWithZone:zone];
        } else {
            return [MasterDetailViewController_iPad allocWithZone:zone];
        }
    }
}

Этот код не работает и является своего рода демонстрацией концепции. Есть ли способ сделать то, что я пытаюсь сделать, или я смотрю на вещи все неправильно?

РЕДАКТИРОВАТЬ : Просто чтобы прояснить, данные одинаковы между супер и подклассами. Единственным отличием будет пара реализаций метода. Идея состоит в том, что создание подклассов чище, чем специфический для устройства код спагетти.

1 Ответ

1 голос
/ 23 апреля 2011

Скорее всего, ваш код не работает, потому что self внутри метода класса является объектом класса, поэтому [self class] является классом класса . Попробуйте просто [self isEqual:[MasterDetailViewController_iPad class]]. Вы также можете перевернуть сравнение, примерно так:

+ (id)allocWithZone:(NSZone *)zone {
    // Allocating a subclass, don't interfere
    if (![self isEqual:[MasterDetailViewController class]]) {
        return [super allocWithZone:zone];
    }

    // Select an appropriate subclass to create instead
    if ([[UIDevice currentDevice] userInterfaceIdiom]==UIUserInterfaceIdiomPhone) {
        return [MasterDetailViewController_iPhone allocWithZone:zone];
    } else {
        return [MasterDetailViewController_iPad allocWithZone:zone];
    }
}

Это может быть немного легче расширить, если у вас есть причина для большего количества подклассов для конкретного устройства.

Обратите внимание, что есть и другие способы сделать это. Например, вместо подклассов, специфичных для устройства, один общий класс может выделять и использовать объект-помощник, специфичный для устройства, для обработки нескольких операций, которые должны быть разными (вроде делегата). Или вместо переопределения allocWithZone: можно получить метод init базового класса release self и вместо этого выделять и возвращать новый объект соответствующего подкласса. Или вы можете использовать фабричный метод для выделения соответствующего подкласса для конкретного устройства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...