如果一个类没有文档指定的初始化程序怎么办?

时间:2012-10-30 20:13:46

标签: objective-c ios cocoa-touch

我正在寻找有关如何处理这种情况的一般指导。这是一个具体的例子。

我是UIImageView的子类,我希望覆盖initWithImage以在使用提供的图像使用超类init本身之后添加我自己的初始化代码。

但是,UIImageView没有文档化的指定初始化程序,所以我应该调用哪个超类初始化程序来确保我的子类正确初始化?

如果某个类没有指定初始值设定项,请执行以下操作:

  1. 假设调用任何类(UIImageView)初始值设定项是安全的吗?
  2. 查看指定初始化程序的超类(UIView)?
  3. 在这种情况下,#1似乎是答案,因为在我的重写初始值设定项中执行以下操作是有意义的:

    - (id)initWithImage:(UIImage *)image
    {
        self = [super initWithImage:image];
        if (self) {
            // DO MY EXTRA INITIALIZATION HERE
        }
        return self;
    }
    

5 个答案:

答案 0 :(得分:5)

UIImageView有两个初始值设定项,因此您可能需要确保子类处理这两个初始化路径。

您只需声明-initWithImage: 您的指定的初始化程序,并且不支持所有其他初始化程序。

此外,您可以实现-initWithImage:highlightedImage:并抛出异常以指示它不受支持。

或者,您可以将-initWithImage:highlightedImage:声明为指定的初始化程序,并-initWithImage:调用您指定的初始化程序。

或者,您可能会发现,无论您的班级是使用-initWithImage:还是-initWithImage:初始化,都会调用-initWithImage:highlightedImage:初始值设定项。

答案 1 :(得分:4)

UIImageView文档非常糟糕。它显示了两个初始化器,但是你可以进入它们都没有被调用的情况。例如,我正在使用IB,只有initWithCoder:被调用。

- (id)init
{
    return [super init];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    return [super initWithCoder:aDecoder];
}

- (id)initWithFrame:(CGRect)frame
{
    return [super initWithFrame:frame];
}

- (id)initWithImage:(UIImage *)image
{
    self = [super initWithImage:image];
    return self;
}

- (id)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage
{
    self = [super initWithImage:image highlightedImage:highlightedImage];
    return self;
}

子类UIImageView的唯一正确方法是子类化所有初始化器,并且每个子类只能调用具有相同名称的父级初始化器。例如:

subclass -init可以致电UIImageView -init,但无法致电UIImageView -initWithCoder:

是的,没有指定是真正的痛苦。

答案 2 :(得分:2)

没有指定初始化程序时的危险是,您可能调用的任何初始化程序都可以根据其他一个初始化程序执行其工作。在这种情况下,它可能会意外地调用您的一个覆盖,这将无法按照预期的方式工作。

如果你的类只有一个初始化器并且它是超类初始化器的覆盖,那么它可以安全地调用它覆盖的初始化器。那是因为超级初始化程序不会(直接或间接)重新进入自身,所以它不可能重新进入你的覆盖。

您的类也可以实现任意数量的初始值设定项,只要它们的 none 与超类中的任何同名。由于您的名字是唯一的,因此任何超类初始化程序都不会意外地调用它们。

答案 3 :(得分:1)

每个派生自NSObject的类都有init方法作为一个初始化程序,它将为该对象执行初始化过程。因此,如果您不确定,可以始终在自定义初始值设定项中使用self = [super init]。考虑到UIImageView有两个由apple提供的初始值设定项这一事实,您可能必须覆盖它们或向用户抛出一个不能使用此方法的异常(不推荐)。

例如: -

- (id)initWithCustomParam:(NSString *)param {

    if (self = [super init]) {
        self.myparam = param;
    }
    return self;
}

然后你可以实现其他初始化器,

- (id)initWithImage:(UIImage *)image {

    if (self = [self initWithCustomParam:@"default value"]) {
        self.image = image;
    }
    return self;
}

或定义,

- (id)initWithImage:(UIImage *)image customParam:(NSString *)string {

    if (self = [self initWithCustomParam:string]) {
        self.image = image;
    }
    return self;
}

答案 4 :(得分:1)

另一种方法是懒惰。 您可以使用viewDidLoad或viewDidMoveToSuperview等方法进行一些设置。这实际上取决于设置何时重要。