【问题标题】:Overriding init in subclass在子类中覆盖init
【发布时间】:2010-12-05 15:53:30
【问题描述】:

在Objective-C中,是否需要重写子类所有继承的构造函数来添加自定义初始化逻辑?

例如,对于具有自定义初始化逻辑的 UIView 子类,以下内容是否正确?

@implementation CustomUIView

- (id)init {
    self = [super init];
    if (self) {
        [self initHelper];
    }
    return self;
}

- (id)initWithFrame:(CGRect)theFrame {
    self = [super initWithFrame:theFrame];
    if (self) {
        [self initHelper];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [super initWithCoder:decoder];
    if (self) {
        [self initHelper];
    }
    return self;
}

- (void) initHelper {
    // Custom initialization
}

@end

【问题讨论】:

    标签: objective-c inheritance uiview initialization init


    【解决方案1】:

    每个 Cocoa Touch(和 Cocoa)类都有一个指定的初始化器;对于UIView,如in this documentation 所述,该方法为initWithFrame:。在这种特殊情况下,您只需要覆盖initWithFrame;所有其他调用最终将级联并命中此方法。

    这超出了问题的范围,但如果您最终创建了一个带有额外参数的自定义初始化程序,您应该确保在分配 self 时为超类指定了指定的初始化程序,如下所示:

    - (id)initWithFrame:(CGRect)theFrame puzzle:(Puzzle *)thePuzzle title:(NSString *)theTitle {
        self = [super initWithFrame:theFrame];
        if (self) {
            [self setPuzzle:thePuzzle];
            [self setTitle:theTitle];
            [self initHelper];
        }
        return self;
    }
    

    【讨论】:

    • 所以即使我用普通的 init 实例化 CustomUIView,它也会调用 initWithFrame?
    • 需要记住的重要一点是,如果从 NIB 实例化一个对象,则会调用 initWithCoder:,而 NOT initWithFrame:
    • @Pascal 这是一个很好的观点,可能应该从关于initWithFrame 的答案中引用的文档中编辑到答案中:“如果您使用 Interface Builder 来设计您的界面,这个当您的视图对象随后从 nib 文件加载时,不会调用该方法。"
    • 所以对于@Pascal cmets,Sam 接受的答案是错误的。由于您不能依赖构造函数的约定,因此假设您必须覆盖所有构造函数以确保每次都运行您的 init 可能会花费更少的时间。
    • @GregoryJohnson 不一定是全部initWithCoder: 是特殊的,它是 NSCoding 类别的一部分。您可以覆盖指定的初始化程序 initWithFrame: 在这种情况下 PLUS initWithCoder:
    【解决方案2】:

    在使用Interface Builder的情况下,调用的是:

    - (id)initWithCoder:(NSCoder *)coder
    {
        self = [super initWithCoder:coder];
        if (self) {
           //do sth
        }
        return self;
    }
    

    【讨论】:

      【解决方案3】:

      一般来说,您应该遵循指定的初始化约定。指定的初始化程序是 init,它涵盖了所有实例变量的初始化。指定的初始化器也是一个类的其他init方法调用的方法。

      Apple 的 documentation 关于指定初始化程序。

      initWithFrame: 是 NSView 类的指定初始化器。 Apple 的 Cocoa 文档总是明确提到类的指定初始化器。

      initWithCoder: 正在讨论here on SO

      【讨论】:

        猜你喜欢
        • 2014-12-04
        • 2014-08-22
        • 2020-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-31
        相关资源
        最近更新 更多