我有一个名为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代码?
答案 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。