9

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

我是 UIImageView 的子类化,并且我想重写 initWithImage 以在超类 init 本身与提供的图像之后添加我自己的初始化代码。

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

如果一个类没有指定初始化器,我是否:

  1. 假设调用任何类的 (UIImageView) 初始化程序是安全的?
  2. 查看指定初始化程序的超类(UIView)?

在这种情况下,#1 似乎是答案,因为在我的重写初始化程序中执行以下操作是有意义的:

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

5 回答 5

5

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

您可以简单地声明这-initWithImage:指定的初始化程序,并且不支持所有其他初始化程序。

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

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

或者,您可能会发现-initWithImage:无论您的类是否使用-initWithImage:或初始化,都会调用您的初始化程序-initWithImage:highlightedImage:

于 2012-10-30T20:32:53.593 回答
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:

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

于 2013-10-07T22:21:35.677 回答
2

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

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

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

于 2013-10-08T00:16:09.483 回答
1

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

例如:-

- (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;
}
于 2012-10-30T21:36:32.757 回答
0

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

于 2013-10-08T00:40:11.573 回答