1

我有以下情况:我正在扩展UITextView control (MyTextView : UITextView). 根据运行时设备版本,我有不同的实现。所以目前我在MyTextView类的实现中有很多“if-else”语句。

为了使其更易于维护,我想将它分成不同的类:

MyTextViewIos5 : MyTextView,MyTextViewIos6:MyTextView

创建一个工厂函数,该函数将在运行时根据设备 iOS 版本知道要创建哪个子类

如果我使用 MyTextView 作为参数,此解决方案非常有效。

MyTextView* textView = [Factory createWithFrame:frame];

当有一个类继承MyTextView (externalTextView:MyTextView)并使用特定方法扩展它时,问题就开始了,它的initWithFrame方法如下所示:

- (id)initWithFrame:(CGRect)frame {
    self = [Factory createWithFrame:frame];
    if (self) {
        ...
    }
    return self;
}

我没有打电话给超级,而是打电话initwithFrame给我的工厂。

当我调用externalTextView特定方法时,应用程序崩溃并显示MyTextViewIos5MyTextViewIos6未实现所调用的特定方法的错误。

是否有使其工作的解决方法?

4

2 回答 2

1

只需为或不为您的自定义类分配self = [Factory createWithFrame:]初始化数据。结果,您的自定义类的方法表等不存在,这就是它崩溃的原因。MyTextViewIos5MyTextViewIos6

继承的本质是你必须要么子类化MyTextViewIos5 MyTextViewIos6才能继承它们的特性。问题是你不知道是哪个。

我建议将自定义类的功能分离为委托/协议设计。MyTextView 超类可以包含用于管理委托的代码。

就像是:

- (void)methodCustomSubclassWouldHaveOverridden
{ 
   [delegate handleThisForMe];
}
于 2013-07-11T18:54:19.200 回答
0

如果您定义了一个,则您派生的每个类MyTextView都应调用[super initWithFrame]其自己的方法。initWithFrame如果您不需要对派生类实例进行任何自定义初始化,则可以完全省略 init 方法。

在一般情况下,您的工厂createWithFrame应该是这样的:

- (MyTextView*)createWithFrame:(CGRect)frame {

    if (<iOS6>)
         return [[MyTextViewOS6 alloc] initWithFrame];
    if (<iOS5>)
         ...
}

现在,如果您的派生类不需要任何特殊的初始化,您可以简单地initWIthFrame在每个派生类中保留方法(并且只在基类中定义一个)。

或者,您可以在工厂中进行初始化,如下所示:

- (MyTextView*)createWithFrame:(CGRect)frame {

    if (<iOS6>)
         MyTextViewOS6* view = [[MyTextViewOS6 alloc] initWithFrame];
         view.iOS6SpecificProperty = ...;
         [view iOS6SpecificMethod:...];
         return view;
    if (<iOS5>)
         ...
}

你在做什么:

self = [Factory createWithFrame:frame];

正在分配一个新实例MyTextView并替换self原始值。换句话说,当你这样做时:

externalTextView* view = [[externalTextView alloc] initWithFrame];

首先为类型的对象分配内存externalTextView;然后,调用该类的 initWithFrame 方法。现在,如果在 initWithFrame 内部,您可以:

self = [Factory createWithFrame:frame];

您正在通过工厂实例化一个新对象并为其分配一个指针self(该指针最初指向通过 alloc 创建的对象)。

希望这可以帮助。

于 2013-07-11T19:22:57.027 回答