RFInitializing
通过使用 RFInitializing,对象的初始化变得更容易。
让我们通过一个示例来比较一下。
在根类中
之前 | 之后 |
---|---|
@implementation BaseView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self commonSetup];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self commonSetup];
}
return self;
}
- (void)commonSetup {
// do something
}
@end |
@implementation BaseView
RFInitializingRootForUIView
- (void)onInit {
// do the common setup
}
- (void)afterInit {
// do somthing after the inistance
// has been initialized
}
@end |
在子类中
之前 | 之后 |
---|---|
@implementation FooView
- (instancetype)initWithBar:(Bar)bar {
self = [super initWithFrame:CGRectZero];
if (self) {
[self commonSetupForSubclasss];
_bar = bar;
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self commonSetupForSubclasss];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self commonSetupForSubclasss];
}
return self;
}
- (void)commonSetupForSubclasss {
// do something
}
@end |
@implementation FooView
- (instancetype)initWithBar:(Bar)bar {
self = [super initWithFrame:CGRectZero];
if (self) {
_bar = bar;
}
return self;
}
- (void)onInit {
[super onInit];
// common setup for subclasss
}
@end |
目的
一遍又一遍地写 init 方法很无聊,尤其是有太多要覆盖的 init 方法。例如,如果您想子类化 UIView,您可能需要覆盖 init、frameInit 和 initWithCoder 方法。如果您想从该类创建子类,您也必须再次覆盖这些方法,WTF。
是时候结束这些无意义的重复了。通过符合 RFInitializing
,您只需要在根类中写一次这些 init 方法,然后子类中只需实现 onInit
和 afterInit
,不再要有 init。
注意,如果一个类符合 RFInitializing,则在初始化期间和 init 方法返回之前应该调用 onInit
。但 afterInit
应在该方法完成并通常调用 init 方法后调用。例如
- (void)viewDidLoad {
[super viewDidLoad];
// RFButton conforms to RFInitializing.
RFButton *button = [[RFButton alloc] init];
// `onInit` was called before here.
// Do some config.
button.icon = [UIImage imageNamed:@"pic"];
// Any other code.
// `afterInit` won't be called in this scope.
}
// `afterInit` will be called after viewDidLoad executed in this example.
使用
您应该在符合此协议的根对象中调用 onInit
和 afterInit
。并且 afterInit
必须延迟。以下是一个示例
- (id)init {
self = [super init];
if (self) {
[self onInit];
// Delay execute afterInit, you can also use GCD.
[self performSelector:@selector(afterInit) withObject:self afterDelay:0];
}
return self;
}
在子类中,您不能在 init 方法中调用这些方法。您可以为您自己的定制实现 onInit
或 afterInit
。并且,如果覆盖了 onInit
或 afterInit
,在实现中应某个点调用 super。
// If you had to add another init method.
- (instancetype)initWithSomething:(id)some {
self = [super init];
if (self) {
// Don't call onInit or afterInit.
self.something = some;
}
return self;
}
- (void)onInit {
[super onInit];
// Something
}
- (void)afterInit {
[super afterInit];
// Something
}
更多
你可以在https://github.com/RFUI找到更多示例,例如RFCheckbox。