在objective-c中覆盖和自定义inits

时间:2015-06-15 12:31:27

标签: ios initialization overwrite

我有一个继承MPMoviePlayerViewController的类。我尝试重写init方法,以便我不必为每个其他-initWithSomething函数重复代码。对于自定义initWithSomething方法,这将起作用。但我无法弄清楚如何使其适用于继承的iniWithSomething方法

-(instancetype)init
{
    if(self = [super init]){
        // This is code I don't want to repeat in initWithSomething methods
        [self startWithHiddenControls];

        AVAudioSession *audioSession = [AVAudioSession sharedInstance];
        [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
        [audioSession setActive:YES error:nil];

        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:UIApplicationDidEnterBackgroundNotification
                                                      object:nil];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(UIApplicationDidBecomeActive)
                                                     name:UIApplicationDidBecomeActiveNotification
                                                   object:nil];
    }
    return self;
}

-(instancetype)initWithContentURL:(NSURL *)contentURL
{

    // Not overwriting doesn't use my overwriten init so i must do it.
    // But how ?!?
    // why [super init] makes inifinite loop? (I know the norm is [super <same method>])
    if(self = [self init]){} // this will not work. Inifinite loop I believe.

    return self;
}

//This method works fine
- (instancetype)initWithSettings:(NSDictionary *)settings
{
    // [self init] works here but HOW?
    if(self = [self init]){
        //my custom stuff
    }
}

在写这篇文章的过程中,我发现[super init]调用-(instancetype)initWithContentURL:(NSURL *)contentURL并存在无限循环问题。为什么指定的初始值设定项init会调用辅助初始值设定项initWithURL?它应该不是相反吗?请解释一下。

这是否意味着我应该使用initWithURL方法而不是init方法来放置我不想重复的代码。

编辑:这就是我所做的。我在initWithURL方法中输入了代码。现在,默认的init和我的自定义init都将运行它。

2 个答案:

答案 0 :(得分:2)

为什么要将init称为指定的初始值设定项?我相信,事实并非如此。我们来参考the docs

  

指定的初始值设定项在类中起着重要作用。它   确保通过调用初始化继承的实例变量   超类的指定初始值设定项。 通常是   init ...具有最多参数且大部分参数的方法   初始化工作,它是辅助的初始化程序   该类的初始化程序调用自己的消息。

所以它似乎并不满足这两个特征:它具有最少数量的参数,显然它用initWithContentURL调用另一个初始值设定项(self)。所以,我相信,如果你找到真正的指定初始化程序,一切都会按预期工作。

根据MPMoviePlayerViewController class reference,指定的初始值设定项为initWithContentURL。因此,您只需覆盖它而不是init

答案 1 :(得分:0)

只需创建一个私有方法并将您的公共代码放在那里,例如

- (void)commonInitialization {
    [self startWithHiddenControls];
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
    [audioSession setActive:YES error:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(UIApplicationDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
}

然后在你的inits中使用:

- (instancetype)initWithContentURL:(NSURL *)contentURL {
    self = [super initWithContentURL:contentURL];
    if (self) {
        [self commonInitialization];
        // everything else
    }
    return self;
}