如何获取子类将属性初始化为正确的类?

时间:2013-08-15 16:56:58

标签: ios objective-c cocoa-touch

我有一个名为SPPanelManager的类,它具有另一个类的属性,名为SPPanelSettingsManager。 SPPanelManager的-init方法中包含以下内容:

self.settingsManager = [[SPPanelSettingsManager alloc] init];

SPPanelManager的目的是进行子类化,并且在我的应用程序中使用子类。例如,有SPGreetingManager。在SPGreetingManager的.h文件中,我声明了:

@property (nonatomic, strong) SPGreetingSettingsManager *settingsManager;

使settingsManager成为正确的类。问题是,当初始化SPGreetingManager子类时,它会调用上面的init方法,并将settingsManager初始化为SPPanelSettingsManager类,而不是SPGreetingSettingsManager

如何将其初始化为该属性的正确类,而无需在每个子类中重写init代码?

3 个答案:

答案 0 :(得分:8)

超类(SPPanelManager)必须知道具体小组经理想要将哪个类用作settingsManager

Apple使用以下方法将CALayers与UIViews匹配:

基类声明了一个返回具体SPPanelSettingsManager子类的类方法:

// in SPPanelManager.h
+ (Class)settingsManagerClass;

...哪些子类重写以返回其自定义类:

// in SPGreetingManager.m
+ (Class)settingsManagerClass
{
    return [SPGreetingSettingsManager class];
}

现在,超类可以按如下方式实例化设置管理器:

self.settingsManager = [[[[self class] settingsManagerClass] alloc] init];

答案 1 :(得分:1)

另一种常见的解决方案是使用命名约定。只需匹配类的名称:SPGreetingManager有一个SPGreetingSettingsManager

根据定义,每个......管理员必须有匹配的... SettingsManager。

// in SPPanelManager.m init
NSString *className = NSStringFromClass([self class]);
className = [className stringByReplacingOccurrencesOfString:@"Manager"
                                                 withString:@"SettingsManager"];
Class settingsManagerClass = NSClassFromString(className);
NSAssert(settingsManagerClass != Nil, @"no settings manager class found");

self.settingsManager = [[[settingsManagerClass settingsManagerClass] alloc] init];

优点是子类不必重写声明类类型的公共方法。另一方面,似乎有点混淆了正在发生的事情。

此外,上面的代码强制了类之间的一对一关系。没有设置控制器可以重复使用。

答案 2 :(得分:0)

SPPanelManager是您开发的一个类吗?只需给它一个带有设置实例参数的init。