众所周知,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时,控制台会打印pleaseanswer the door。
Hey,等一等。为什么我会在两个ViewController中都看到了somebody is knocking?
不用看了,subclass对象的words属性确实是please answer the door。如果你正在调试代码,那么可以debug区中确认这一点。
问题在于subclass的初始化出现了问题。看这一句:self=[super initWithNibName: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也无法指向类链。
thx:http://blog.csdn.net/kmyhy/article/details/7236619
btw:
现在是
1. subclass->initWithNibName
2. superclass->initWithNibName
3. superclass->setWords
4. subclass->setWords
5. subclass->viewDidLoad
6. superclass->viewDidLoad
打印:在加载superclass.xib时,控制台将打印somebodyis knocking。而加载subclass.xib时,控制台会打印pleaseanswer the door。
以上ios6测试
相关推荐
每个ios开发者对loadView和viewDidLoad肯定都很熟悉,虽然这两个函数使用上真的是非常简单,但是和类似的initWithNibName/awakeFromNib/initWithCoder放在一起还是非常容易让人混淆的. 昨天看了下苹果官方的相关文档...
self.super:initWithNibName_bundle("MyControllerView.xib", nil) return self end function viewDidLoad() -- 这里执行其他视图加载操作 end ``` 然而,Wax在实际应用中也存在一些局限性。例如,Wax的`wax_...
1. UIViewController调用顺序:`initWithNibName:bundle:` -> `loadView` -> `viewDidLoad` -> 使用视图 -> `viewDidUnload` -> `dealloc`。`initWithNibName:bundle:`初始化,`loadView`加载视图,`viewDidLoad`...
在上述代码中,我们重写了这些初始化方法来打印日志,以便观察各个方法的执行顺序。`awakeFromNib`方法在从XIB或Storyboard加载视图时被调用,而`layoutSubviews`则在视图需要布局时自动调用,例如在屏幕旋转或者父...
5. `viewDidAppear:` 和 `viewDidDisappear:` 视图完全显示和完全消失后调用,可用于执行一些动画效果或清理工作。 在实际项目中,我们可能会遇到多个视图控制器协作的情况,比如通过导航控制器...
这可能导致未预期的代码执行顺序,比如数据源的赋值发生在`viewDidLoad`之前,从而导致数据无法正常显示。 因此,正确的做法是在`viewDidLoad`或更晚的生命周期方法中设置`self.view`的属性,如`viewWillAppear:`或...
AutoLayoutFlowDemo AutoLayoutFlowDemo 这个Demo主要用来展示约束到布局生效的过程。 并不针对约束的使用说明,是...1. -initWithNibName 如果使用 StoryBoard 加载 ViewController ,则会直接调用 -initWithCoder
- `initWithNibName:bundle:`:当从故事板或 nib 文件加载View Controller时,此方法被调用,传入 nib 文件名和资源包。 - `awakeFromNib`:当 nib 文件加载完成后,此方法会被调用,此时View Controller的所有...
`viewDidLoad`和`viewDidUnload`分别在视图加载完成和卸载后被调用,用于初始化和清理工作。`shouldAutorotateToInterfaceOrientation:`决定了控制器能否根据设备方向自动旋转界面。 `UIView`是所有可视控件的基类...
3. **生命周期方法**:如`viewDidLoad`、`viewWillAppear`、`viewDidAppear`、`viewWillDisappear`和`viewDidDisappear`等,这些方法在视图控制器的生命周期中被调用,是添加额外逻辑的好时机。 4. **导航控制器** ...
4. **管理Tab的顺序和可见性** - 可以通过`viewControllers`属性获取或设置TabBarController的子视图控制器数组,通过调整数组顺序改变Tab的显示顺序。 - 若要隐藏某个Tab,可以将其从数组中移除,但需要注意不要...
初始化方法-(id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle用于加载指定的nib文件,nibName不包含扩展名,nibBundle指定了nib文件所在的资源包。当视图加载完成后,系统会调用-(void)...
`initWithNibName:bundle:`方法是初始化控制器的地方,这里主要进行自定义初始化,但在这个例子中并未有特别的定制。 `scrollToNextPage:`方法是用于定时滚动的核心,它根据当前页码和`UIScrollView`的大小计算出...
- `(id)initWithNibName:(NSString*)nibName bundle:(NSBundle*)bundle;`:这是一个常见的初始化方法,可以在这里进行一些基本的初始化工作。 - `-(void)awakeFromNib`:这个方法会在从XIB文件加载完毕后调用,...
- 在`viewDidLoad`方法中初始化数据源和TableView。 3. **数据源方法**: - `numberOfSectionsInTableView:`:返回分组的数量。 - `tableView:numberOfRowsInSection:`:对于每个分组,如果该分组被展开,则返回...
这篇教程将详细介绍如何在iOS中自动生成表格效果,适用于初学者和有一定经验的开发者,旨在提高开发效率并提供一种简洁的界面展示方式。 首先,我们要了解在iOS中实现表格效果通常有几种方法:使用UITableView、...
FirstViewController *first = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil]; ``` 需要注意的是,使用XIB文件时,应避免文件名与控制器类名相似,以免造成混淆和错误。 ### ...
3. **构造方法(Init Methods)**:初始化方法如`-init`,`-initWithCoder:`和`-initWithNibName:bundle:`用于创建并设置新对象的状态。 4. **分类(Categories)**:使用`+load`和`+initialize`方法,可以在类加载...