Created
January 15, 2015 12:01
-
-
Save steipete/6d92218e055d195ebb05 to your computer and use it in GitHub Desktop.
Ensure people call the right init
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define PSPDF_EMPTY_ASSERTING_INIT() \ | |
_Pragma("clang diagnostic push") \ | |
_Pragma("clang diagnostic ignored \"-Wobjc-designated-initializers\"") \ | |
- (instancetype)init \ | |
{ \ | |
NSAssert(NO, @"Use the designated initializer to create an instance of this object."); \ | |
return nil; \ | |
} \ | |
_Pragma("clang diagnostic pop") |
If you have to do so, it means that you have the designated initializers chain broken.
On an app I have these view controller with different designated initializers:
@interface AVERegistrationViewController : UIViewController
- (instancetype)initForFirstRegistration:(BOOL)firstRegistration;
@end
@implementation AVERegistrationViewController
// This class designated initialiser
- (instancetype)initForFirstRegistration:(BOOL)firstRegistration {
// call super's designated initializer
self = [super initWithNibName:nil bundle:nil];
if (!self) {
return nil;
}
_firstRegistration = firstRegistration;
return self;
}
// Override super's designated initializer calling this class' designated initializer
- (instancetype)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle {
return [self initForFirstRegistration:YES];
}
@end
@interface AVEUserViewController : AVERegistrationViewController
- (instancetype)initWithUser:(AVEUser *)user;
@end
@implementation AVEStepViewController
// This class designated initialiser
- (instancetype)initWithUser:(AVEUser *)user {
// call super's designated initializer
self = [super initForFirstRegistration:YES];
if (!self) {
return nil;
}
_user = user;
return self;
}
// Override super's designated initializer calling this class' designated initializer
- (instancetype)initForFirstRegistration:(BOOL)firstRegistration {
return [self initWithUser:nil];
}
@end
If you do [[AVEUserViewController alloc] init]
it does this:
NSObject
init
is called;UIViewController
ovveridesinit
to callinitWithNibName:bundle:
(its designated initializer);AVERegistrationViewController
overridesinitWithNibName:bundle:
to callinitForFirstRegistration:
(its designated initializer);AVEStepViewController
overridesinitForFirstRegistration:
to callinitWithUser:
.
So, as long as every secondary initializer calls the designated one and each subclass overrides super's designated initializer to keep the links in the chain, you're safe and you can initialize objects as you prefer.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
why don't you use switf's approach to forward calls to designated initializer?