【问题标题】:How to make settings inheritance如何进行设置继承
【发布时间】:2014-04-30 00:39:54
【问题描述】:

在我的 XCode 项目中,我想要一些默认设置设置,基本上是一组变量,如 GlobalTintColor、ServerUrl 等。 然后,我需要为每个客户端/目标覆盖其中的一些设置。 这些设置仅用于间隔使用,这意味着我不是在寻找设置捆绑类型的解决方案。 我不想有重复的设置,所以某种继承似乎是正确的方法。

我想我会创建一个包含所有默认设置的父类,然后为每个客户端创建一个子类,根据需要覆盖设置。我只是不知道如何加载这些设置。我认为只有需要覆盖设置的客户端才有子类。其他客户端只是使用父类定义的默认设置。

但是当我在应用程序启动时加载设置时,我需要检查子类是否可用,如果不可用,我只加载超类。

但是我得到了设置是哪种类的问题:子类还是超类? 我一直在研究类别和类聚类,但到目前为止还没有找到解决方案。 在我看来,这是许多应用程序开发人员需要的功能。你们有谁知道解决这个问题的好模式吗?

举例说明:

- (id) getAppConfigurationSettings {

    id settings;

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

    return settings;

}

【问题讨论】:

    标签: ios objective-c inheritance settings


    【解决方案1】:

    你想要这样的东西吗?

    “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

    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]];
    
    }
    

    注意-以上代码未经测试可能不完全正确,但可以这样。

    【讨论】:

    • 是的,谢谢,这部分我记下来了。对我来说棘手的部分是我如何实例化正确的类。
    • 为此,您可以定义一些枚举并相应地初始化类。请参阅我的更新答案。
    【解决方案2】:

    当我听到“基础”和“覆盖”时,我立即想到了类的层次结构,所以@iphonic 的回答做得很好,尽管我会以稍微不同的方式设计它:

    基本设置

    @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:注意:如果子类或相同,后一种方法返回 YES,比较时要考虑的事项。

    一旦你找到一个继承自BaseSettings 的类,你就可以打破循环并实例化找到的类(例如使用class_createInstance())。一个(未经测试的)骨架是这样的:

    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

    【讨论】:

      猜你喜欢
      • 2019-01-12
      • 1970-01-01
      • 1970-01-01
      • 2011-09-16
      • 2011-12-08
      • 1970-01-01
      • 2019-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多