当我听到“基础”和“覆盖”时,我立即想到了类的层次结构,所以@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