objective-c 中的覆盖和自定义初始化
Overwriting and custom inits in objective-c
我有一个 class 继承了 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
}
}
在写这个post的过程中,我发现[super init]
调用了-(instancetype)initWithContentURL:(NSURL *)contentURL
,这就是死循环问题。为什么指定初始化器 init
调用辅助初始化器 initWithURL
?不应该反过来吗?请解释。
这是否意味着我应该将我不想重复的代码放在 initWithURL
方法而不是 init
方法中。
编辑:这就是我所做的。我在 initWithURL 方法中输入了代码。现在默认的 init 和我的自定义 init 都会 运行 它。
只需创建一个私有方法并将您的公共代码放在那里,例如
- (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];
}
然后在你的初始化中使用:
- (instancetype)initWithContentURL:(NSURL *)contentURL {
self = [super initWithContentURL:contentURL];
if (self) {
[self commonInitialization];
// everything else
}
return self;
}
为什么称 init
为指定初始化器?我相信,事实并非如此。参考一下the docs:
The designated initializer plays an important role for a class. It
ensures that inherited instance variables are initialized by invoking
the designated initializer of the superclass. It is typically the
init... method that has the most parameters and that does most of the
initialization work, and it is the initializer that secondary
initializers of the class invoke with messages to self.
所以它似乎不满足这两个特性:它的参数数量最少,而且显然它用 self
调用了另一个初始化程序 (initWithContentURL
)。所以,我相信,如果你找到了真正的指定初始化器,一切都会按预期工作。
根据MPMoviePlayerViewController class reference,指定初始化器是initWithContentURL
。所以你可以简单地覆盖它而不是 init
.
我有一个 class 继承了 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
}
}
在写这个post的过程中,我发现[super init]
调用了-(instancetype)initWithContentURL:(NSURL *)contentURL
,这就是死循环问题。为什么指定初始化器 init
调用辅助初始化器 initWithURL
?不应该反过来吗?请解释。
这是否意味着我应该将我不想重复的代码放在 initWithURL
方法而不是 init
方法中。
编辑:这就是我所做的。我在 initWithURL 方法中输入了代码。现在默认的 init 和我的自定义 init 都会 运行 它。
只需创建一个私有方法并将您的公共代码放在那里,例如
- (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];
}
然后在你的初始化中使用:
- (instancetype)initWithContentURL:(NSURL *)contentURL {
self = [super initWithContentURL:contentURL];
if (self) {
[self commonInitialization];
// everything else
}
return self;
}
为什么称 init
为指定初始化器?我相信,事实并非如此。参考一下the docs:
The designated initializer plays an important role for a class. It ensures that inherited instance variables are initialized by invoking the designated initializer of the superclass. It is typically the init... method that has the most parameters and that does most of the initialization work, and it is the initializer that secondary initializers of the class invoke with messages to self.
所以它似乎不满足这两个特性:它的参数数量最少,而且显然它用 self
调用了另一个初始化程序 (initWithContentURL
)。所以,我相信,如果你找到了真正的指定初始化器,一切都会按预期工作。
根据MPMoviePlayerViewController class reference,指定初始化器是initWithContentURL
。所以你可以简单地覆盖它而不是 init
.