2014-03-22 2 views
1

В моем проекте XCode мне нужны настройки по умолчанию, которые в основном представляют собой набор переменных, таких как GlobalTintColor, ServerUrl и т. Д. Затем мне нужно переопределить некоторые из этих настроек на клиент/цель. Эти настройки предназначены только для использования интервалов, а это значит, что я не ищу решение типа набора параметров. Я не хочу иметь повторяющиеся настройки, поэтому какое-то наследование кажется правильным путем.Как сделать наследование настроек

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

Но когда я загружаю настройки при запуске приложения, тогда мне нужно проверить, доступен ли подкласс, а если нет, я загружаю только суперкласс.

Но тогда у меня возникла проблема с классом настроек: подкласс или суперкласс? Я изучал категории, а также кластеры классов, но пока не нашел решения. Кажется, это функциональность, которую нужно многим разработчикам приложений. Кто-нибудь из вас знает о хорошем шаблоне для решения этой проблемы?

Для иллюстрации:

- (id) getAppConfigurationSettings { 

    id settings; 

    if ([AppConfigurationSettings class]) { 
     settings = [AppConfigurationSettings class]; 
    } else { 
     settings = [DefaultAppConfigurationSettings class]; 
    } 

    return settings; 

} 

ответ

0

Вы хотите что-то вроде этого?

"Parent.h"

@interface Parent : NSObject 
@property(nonatomic,strong)UIColor *color; 
@end 

"Parent.m"

#import "Parent.h" 

@implementation Parent 
-(void)setColor:(UIColor *)color{ 
    self.color=color; 
} 
@end 

Затем создается еще один класс, который будет наследовать Parent сказать Child

ребенка. h

#import "Parent.h" 
@interface Child : Parent 

@end 

Child.m

#import "Child.h" 

@implementation Child 
//Override the actual color 
-(void)setColor:(UIColor *)color{ 
    self.color=color; 
} 
@end 

Затем вы можете использовать его как ниже

Parent *parent=[[Parent alloc] init]; 
[parent setColor:[UIColor redColor]]; 

Child *child=[[Child alloc] init]; 
[Child setColor:[UIColor blueColor]]; 

Я надеюсь, что это даст вам достаточно идея ..

Обновлено

Для пользовательской инициализации вы можете создать несколько перечислений, и сделать ваши инициализаций соответственно, как показано ниже

typedef enum { 
    kParent  =  1, 
    kChild  =  2 
}kSettings; 

-(void)updateColor:(kSettings)settingType{ 

    id classObj; 

    switch (settingType) { 
     case kParent: 
      classObj=[[Parent alloc] init]; 
      break; 

     case kChild: 
      classObj=[[Child alloc] init]; 
      break; 

     default: 
      break; 
    } 

    [classObj setColor:[UIColor redColor]]; 

} 

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

+0

Да, спасибо, эта часть я получил вниз. Трудная часть для меня - это то, как я создаю правильный класс. – Telstar

+0

Для этого у вас может быть определен определенный enum и инициализировать класс соответственно. См. Мой обновленный ответ. – iphonic

0

Когда я слышу о «базе» и «переопределить», я сразу же думать о иерархии классов, поэтому @iphonic ответ делает работу очень хорошо, хотя я бы конструировать его в несколько ином виде:

"BaseSettings"

@interface BaseSettings : NSObject 
... properties 
@end 

@implementation BaseSettings 

- (instancetype) init { 
    self = [super init]; 
    if (self) { 
     [self constantInit]; 
     [self dynamicInit]; 
    } 
} 

// Put here initialization that won't be overridden 
// in inherited classes 
- (void) constantInit { 
} 

// Put here initialization that will be overridden 
// in inherited classes 
- (void) dynamicInit { 
} 

@end 

"SettingsInheritor"

@interface SettingsInheritor : BaseSettings 
@end 

@implementation SettingsInheritor 

- (void) dynamicInit { 
    // Call base method so that not overriden settings 
    // are still initialized properly 
    [super dynamicInit]; 

    // Override settings here 
    ... 
} 

Метод constantInit предназначен только для удобства, чтобы визуально отделить константу от переопределяемых настроек - чтобы вы могли избавиться от него, если вам не понадобится или понравится.

Что может быть улучшено в ответе @ iphonic, так это то, как создается экземпляр фактического класса настроек, поэтому я предлагаю другой подход.

Как описано here, вы можете использовать obj_getClassList(), чтобы получить список всех зарегистрированных определений классов - то вы можете перебрать все из них, и проверить, если его суперкласс BaseSettings (или что вы хотите назвать класс настройки базовых) , используя class_getSuperClass() или isSubclassOfClass:. Примечание: последний метод возвращает ДА, если подкласс или идентичный, что следует учитывать при сравнении.

Как только вы найдете класс, наследующий от BaseSettings, вы можете разбить цикл и создать экземпляр найденного класса (например, используя class_createInstance()). A (непроверенных) скелет, как это:

int numClasses = objc_getClassList(NULL, 0); 

if (numClasses > 0) { 
    BOOL found = NO; 
    Class settingsClass; 
    Class *classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses); 

    for (int index = 0; index < numClasses; ++index) { 
     Class curClass = classes[index]; 
     Class superClass = class_getSuperclass(curClass); 
     const char *superClassName = class_getName(superClass); 

     if (strcmp(superClassName, "BaseSettings") == 0) { 
      settingsClass = curClass; 
      found = YES; 
      break; 
     } 
    } 

    if (found) { 
     // Create the class instance from `settingsClass` 
    } 

    free(classes); 
} 

Кредиты Ole Begemann для (большинство) кода выше

Смежные вопросы