众所周知,IB在加载nib的过程中存在着一些undocument行为,有的行为确实是不可理喻的,因此程序员对IB产生了抗拒心理。
今天我们要介绍的是IB导致的一个奇特行为。通过本文的描述, 作者完美地展示了IB给面向对象所带来的破坏作用。
我们有两个View Controller,暂名为superclass和subclass。subclass继承了superclass。在superclass的initWithNibName初始化方法中,我们这样写道:
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[self setWords:@”somebody is knocking”];
}
return self;
在superclass的viewDidLoad方法中,我们这样写:
[super viewDidLoad];
NSLog(@"get XXX:%@", [self words]);
然后我们用subclass继承superclass。在initWithNibName方法中,我们写入:
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {[
[self setWords:@” pleaseanswer the door”];
}
很显然,我们通过覆盖initWithNibName方法,修改了从superclass继承来的words属性。如果我们想打印pleaseanswer the door这段文本,你可能会想重用superclass的viewDidLoad方法:
- (void)viewDidLoad{
[super viewDidLoad];
}
好了,运行程序。在加载superclass.xib时,控制台将打印somebodyis knocking。而加载subclass.xib时,控制台会打印please answer the door。
Hey,等一等。为什么我会在两个ViewController中都看到了somebody is knocking?
不用看了,subclass对象的words属性确实是pleaseanswer the door。如果你正在调试代码,那么可以debug区中确认这一点。
问题在于subclass的初始化出现了问题。看这一句:self=[superinitWithNibName:nibNameOrNil bundle:nibBundleOrNil];
这句代码将导致IB加载nib文件,并立即调用viewDidLoad方法。我们可以看到在初始化subclass时的调用顺序如下:
1. subclass->initWithNibName
2. superclass->initWithNibName
3. superclass->setWords
4. subclass->viewDidLoad
5. superclass->initWithNibName
6. subclass->setProperty
让我再解释一下:
1. 首先subclass的initWithNIbName方法调用。
2. 接着调用superclass的initWithNibName方法。
3. 在superclass的initWithNibName方法中,words属性被设置为somebodyis knoking。
4. superclass的initWithNibName方法结束,表示nib文件已加载,则调用nib文件的File’sowner所指向的 viewDidLoad方法。注意,这时的nib文件名应为subclass.nib,于是应调用[subclass viewDidLoad]方法。
5. subclass的viewDidLoad方法又调用了supclass的viewDidLoad方法。于是控制台打印出的是words属性的当前值somebodyis knoking。
6. 最后才是initWithNibName方法剩余的代码,在这里我们将words属性修改为pleaseanswer the door。但为时已晚,在此之前viewDidLoad已经执行结束。
解决的办法是简单的,不要在initWithName方法中修改从父类继承来的属性,相反,我们可以在[super iewDidLoad]之前这样做:
- (void)viewDidLoad{
[selfsetWords:@” pleaseanswer the door”];
[super viewDidLoad];
}
结论
由于initWithNibName或者是IB 这些限制,.nib文件违反了面向对象的原则。.nib文件无法从另一个.nib文件继承。不管你的类如何继承,但nib文件中不会保存类的层次结构,File’sowner也无法指向类链。
分享到:
相关推荐
NULL 博文链接:https://justsee.iteye.com/blog/1626231
iOS初始化方法包括系统默认的和自定义的,常见系统初始化方法有init, initWithFrame:, initWithNibName:bundle:等,自定义则是各式各样。日常iOS项目开发过程中,我们经常在类的初始化方法中初始化接下来类需要用到...
方法去调用NIB文件初始化自身,即使那没有使用nib文件也会调用这个函数(默认情况下init方法已经为你的做这件事情了),如果你调用这个方法,并传递的两个参数为空(nil),然后类会调用-loadView去读取一个名字和你...
这样做几乎总是会导致难以调试的错误,因为在发出内存警告后,初始化逻辑将不会再次执行。 考虑一个简单的例子: - ( id )initWithNibName:( NSString *)nibNameOrNil bundle:( NSBundle *)nibBundleOrNil { if ...
在要以模态显示的视图控制器的初始化程序中,使用已注册的ModalTransitionType配置模态转换样式。 #pragma mark - Constructor - (id)init { if (self = [super initWithNibName:@"PopupViewControlle
1、在infterface中定义数组并在init方法中初始化 代码如下: NSMutableArray *addressBookTemp; – (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { addressBookTemp = ...
PoPoverViewController * popover = [[[PoPoverViewController alloc]initWithNibName:@"PoPoverViewController" bundle:nil] autorelease]; popover.mainViewController = self; UIPopoverController * pcr = [...
[[ViewController alloc]init]与[ViewController alloc]initWithNibName: bundle: ]的区别 - http://blog.csdn.net/moon_prince2013/article/details/49079173 对UIBackBarButtonItem的理解 - ...
[[ViewController alloc]init]与[ViewController alloc]initWithNibName: bundle: ]的区别 - http://blog.csdn.net/moon_prince2013/article/details/49079173 对UIBackBarButtonItem的理解 - ...
//设置数组容量为0,可变数组随便设置只是个初始化的值 _diJiArr=[[NSMutableArray alloc]initWithCapacity:0]; // CGAffineTransform a = {1,2,3,4,1,1}; //CGAffineTransformMakeRotation 方法的作用就是...
initWithNibName:@"MVYMenuViewController" bundle:nil]; // Create your main content view controller MVYContentViewController *contentVC = [[MVYContentViewController alloc] initWithNibName:@...
使用方法:弹出视图: SamplePopupViewController *samplePopupViewController = [[SamplePopupViewController alloc] initWithNibName:@"SamplePopupViewController" bundle:nil];[self presentPopupViewController...
AutoLayoutFlowDemo AutoLayoutFlowDemo 这个Demo主要用来展示约束到布局生效的过程。 并不针对约束的使用说明,是...1. -initWithNibName 如果使用 StoryBoard 加载 ViewController ,则会直接调用 -initWithCoder
NightModel iOS 夜间模式 夜间模式主要通过 NSNotificationCenter实现, 难点在于可扩展性 与 后期的维护性 ... 不能在 viewDidLoad方法中进行alloc init, 需要将alloc init放到 initWithNibName 中.
可客制化 使用自动版面设计 使用简单 安装及使用方法: 1-您需要将MFComposeClasses文件夹导入到您的项目中 2-添加此行进行显示: MFComposeViewController * composeViewController = [[MFComposeViewController...
JRCamera 如何使用 ...JRCameraViewController *cameraVC = [[JRCameraViewController alloc] initWithNibName:@"JRCameraViewController" bundle:nil]; 2.presentViewController或用导航push都可以。
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return...
IOS图片的原生(Graphics)详解及实例 一,效果图。 二,工程图。 三,代码。 RootViewController.h #import @interface RootViewController : UIViewController ...- (id)initWithNibName:(NSSt
弹出视图控制器用法 PopupViewController * _popViewController = [[PopupViewController alloc] initWithNibName:@"PopupViewController" bundle:[NSBundle mainBundle]]; _popViewController.alertType = ...
AXViewControllerTransitioning 例子 要运行示例项目,请克隆存储库,然后首先从Example目录运行pod install 。 要求 安装 ... 要安装它,只需将以下行...- (instancetype)initWithNibName:(NSString *)nibNameOrNil bun