Ios 类实例化而不在所有构造函数中调用super

Ios 类实例化而不在所有构造函数中调用super,ios,inheritance,constructor,initialization,Ios,Inheritance,Constructor,Initialization,我有以下情况: 我正在扩展UITextView控件(MyTextView:UITextView)。根据运行时设备的版本,我有不同的实现。因此,目前我在MyTextView类的实现中有许多“if-else”语句 为了使其更易于维护,我想将其划分为不同的类: MyTextViewIos5:MyTextView,MyTextViewIos6:MyTextView 并创建一个工厂函数,该函数将在运行时根据设备iOS版本知道要创建的子类 如果我使用MyTextView作为参数,这个解决方案将非常有效 My

我有以下情况: 我正在扩展
UITextView控件(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;
}
- (MyTextView*)createWithFrame:(CGRect)frame {

    if (<iOS6>)
         MyTextViewOS6* view = [[MyTextViewOS6 alloc] initWithFrame];
         view.iOS6SpecificProperty = ...;
         [view iOS6SpecificMethod:...];
         return view;
    if (<iOS5>)
         ...
}
我没有调用super
initwithFrame
而是调用我的工厂

当我调用
externalTextView
specific方法时,应用程序崩溃,错误是MyTextViewIos5或MyTextViewIos6未实现调用的特定方法


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

只需为
MyTextViewIos5
MyTextViewIos6
分配
self=[Factory createWithFrame:]
的inits数据,而不是自定义类。因此,自定义类的方法表等不存在,这就是它崩溃的原因

继承的本质是,为了继承它们的功能,您必须创建子类
MyTextViewIos5
MyTextViewIos6
。问题是你不知道是哪个

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

比如:

- (void)methodCustomSubclassWouldHaveOverridden
{ 
   [delegate handleThisForMe];
}
- (MyTextView*)createWithFrame:(CGRect)frame {

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

只需为
MyTextViewIos5
MyTextViewIos6
而不是自定义类指定
self=[Factory createWithFrame:
初始化数据。因此,自定义类的方法表等不存在,这就是它崩溃的原因

继承的本质是,为了继承它们的功能,您必须创建子类
MyTextViewIos5
MyTextViewIos6
。问题是你不知道是哪个

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

比如:

- (void)methodCustomSubclassWouldHaveOverridden
{ 
   [delegate handleThisForMe];
}
- (MyTextView*)createWithFrame:(CGRect)frame {

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

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

在一般情况下,您的工厂
createWithFrame
应该类似于:

- (void)methodCustomSubclassWouldHaveOverridden
{ 
   [delegate handleThisForMe];
}
- (MyTextView*)createWithFrame:(CGRect)frame {

    if (<iOS6>)
         return [[MyTextViewOS6 alloc] initWithFrame];
    if (<iOS5>)
         ...
}
你在做什么:

self = [Factory createWithFrame:frame];
正在分配
MyTextView
的新实例并替换
self
原始值。换句话说,当您这样做时:

externalTextView* view = [[externalTextView alloc] initWithFrame];
首先,为类型为
externalTextView
的对象分配内存;然后,调用该类的initWithFrame方法。现在,如果在initWithFrame中执行以下操作:

self = [Factory createWithFrame:frame];
您正在通过工厂实例化一个新对象,并将指向它的指针指定给
self
(它最初指向通过alloc创建的对象)


希望这能有所帮助。

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

在一般情况下,您的工厂
createWithFrame
应该类似于:

- (void)methodCustomSubclassWouldHaveOverridden
{ 
   [delegate handleThisForMe];
}
- (MyTextView*)createWithFrame:(CGRect)frame {

    if (<iOS6>)
         return [[MyTextViewOS6 alloc] initWithFrame];
    if (<iOS5>)
         ...
}
你在做什么:

self = [Factory createWithFrame:frame];
正在分配
MyTextView
的新实例并替换
self
原始值。换句话说,当您这样做时:

externalTextView* view = [[externalTextView alloc] initWithFrame];
首先,为类型为
externalTextView
的对象分配内存;然后,调用该类的initWithFrame方法。现在,如果在initWithFrame中执行以下操作:

self = [Factory createWithFrame:frame];
您正在通过工厂实例化一个新对象,并将指向它的指针指定给
self
(它最初指向通过alloc创建的对象)


希望这有帮助。

为什么不想在init方法中调用
super
?我想了一会儿,您可以通过子类化
alloc
来处理这个问题,但可能不行。(这是一种处理原始问题的“聪明”方法。)为什么不想在init方法中调用
super
?我想了一会儿,您可以通过子类化
alloc
来处理这个问题,但可能不行。(这是一种处理原始问题的“聪明”方法。)如果我知道自定义类功能将是什么,这是一个很好的解决方案。但是在我的例子中,我正在构建一个外部SDK,我不能对将要使用\inherit MyTextView类的自定义类做任何假设。@user2572953通过使用协议,您可以定义客户端需要实现的契约。对不起,我的错……我第一次没有正确理解您的解决方案。您是对的,将我的自定义功能放在委托中并在MyTextView类中处理它将起作用。这意味着我的自定义ios5和ios6类不会是MyTextView的子类,而只会实现由它定义的协议。这种方法可以工作,但远不如使用继承优雅。如果我没有其他选择,我会用它。谢谢!如果我知道什么是自定义类功能,这是一个很好的解决方案。但就我而言,我正在构建一个外部SDK,我可以