`
thierry.xing
  • 浏览: 664432 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
580fa9c1-4a0c-3f40-a55a-c9256ce73302
Sencha Touch中...
浏览量:0
社区版块
存档分类
最新评论

initWithNibName导致的初始化问题

    博客分类:
  • iOS
 
阅读更多

 

 众所周知,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也无法指向类链。

分享到:
评论

相关推荐

    initWithNibName和viewDidLoad执行顺序

    `initWithNibName:bundle:`是UIViewController的一个初始化方法,它用于创建一个新的UIViewController实例。这个方法允许我们指定界面的初始加载文件,通常是.xib或.storyboard文件,这些文件包含了UI元素的布局和...

    IOS初始化控制器的实现方法总结

    1. 使用`initWithNibName:bundle:`方法初始化XibViewControllViewController,传入XIB文件的名称和nil作为NSBundle(通常在主bundle中查找)。 2. 创建UIWindow并设置其frame。 3. 将初始化的...

    iOS经验之初始化方法中不该设置self.view的属性浅析

    然而,一个常见的误解是将初始化过程与视图加载混淆,这可能导致一些意料之外的问题。本文将深入探讨为何在初始化方法中不应设置`self.view`的属性,并分析由此引发的潜在问题。 首先,iOS中的初始化方法主要包括...

    iOS XIB创建view

    在这个类中,我们可以添加必要的属性和方法,比如初始化方法、绘制逻辑等。别忘了在XIB文件的Identity Inspector中将"Class"设置为自定义类名。 5. **加载XIB**:在需要使用自定义View的地方,我们需要加载XIB文件...

    initWithCoder与initWithFrame

    方法去调用NIB文件初始化自身,即使那没有使用nib文件也会调用这个函数(默认情况下init方法已经为你的做这件事情了),如果你调用这个方法,并传递的两个参数为空(nil),然后类会调用-loadView去读取一个名字和你...

    iOS最佳实践:iOS软件设计最佳实践

    这样做几乎总是会导致难以调试的错误,因为在发出内存警告后,初始化逻辑将不会再次执行。 考虑一个简单的例子: - ( id )initWithNibName:( NSString *)nibNameOrNil bundle:( NSBundle *)nibBundleOrNil { if ...

    联系人分组列表

    - 在`viewDidLoad`方法中初始化数据源和TableView。 3. **数据源方法**: - `numberOfSectionsInTableView:`:返回分组的数量。 - `tableView:numberOfRowsInSection:`:对于每个分组,如果该分组被展开,则返回...

    百度地图iOS SDK开发教程

    **1.1 初始化BMKMapManager** 在开始之前,你需要在`AppDelegate.h`文件中引入必要的头文件,并定义`BMKMapManager`。这是为了确保可以在应用中正确地使用百度地图的相关功能。 ```objective-c #import #import ...

    Cocoa常用类和方法

    初始化方法-(id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle用于加载指定的nib文件,nibName不包含扩展名,nibBundle指定了nib文件所在的资源包。当视图加载完成后,系统会调用-(void)...

    UIScrollView定时滚动和循环滚动,可点击图片和PageController

    `initWithNibName:bundle:`方法是初始化控制器的地方,这里主要进行自定义初始化,但在这个例子中并未有特别的定制。 `scrollToNextPage:`方法是用于定时滚动的核心,它根据当前页码和`UIScrollView`的大小计算出...

    视图控制对象的区别及使用

    1. `init`: 这是所有对象的初始化方法,但对UIViewController来说,一般不直接使用这个方法初始化,而是使用`initWithNibName:bundle:`或`init(style:)`。 2. `loadView`: 这个方法在视图控制器首次显示时被调用,...

    UIScrollView图片定时滚动和点击

    `- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil`是初始化方法,通常在这里进行自定义的初始化操作,但在这个例子中,我们没有看到具体的初始化内容。 `- (void)...

    cocoa常用类及方法

    `initWithNibName:bundle:`是初始化`UIViewController`的常见方法,`nibName`参数用于指定与该控制器关联的.xib文件名,`nibBundle`则指定xib文件所在的资源包。`viewDidLoad`和`viewDidUnload`分别在视图加载完成和...

    IOS应用源码——TabBarController(标签).zip

    - 在代码中,可以使用`initWithNibName:bundle:`或`init`方法初始化,并通过`setViewControllers:`方法添加子视图控制器。 2. **设置TabBarItem** - TabBarItem是每个Tab的代表,包括图标、标题和选中状态的显示...

    iOS中的View Controller Lifecycle

    例如,可以在`viewDidLoad`中初始化界面元素,在`viewWillAppear:`中设置初始状态,在`viewWillDisappear:`中保存用户数据,等等。 在给定的"Storyboard_unwindDemo"示例中,我们可能看到如何使用Storyboard中的...

    福昕软件招聘iOS开发工程师面试题

    `initWithNibName:bundle:`初始化,`loadView`加载视图,`viewDidLoad`加载完成,`viewDidUnload`释放视图,`dealloc`销毁对象。 2. frame包含view的位置和大小,center是frame的中心点,bounds表示view内容区域。...

    TabBarController标签.rar

    1. **初始化和配置**:`TabBarController`可以通过代码或Storyboard进行初始化。在代码中,可以使用`initWithNibName:bundle:`或`initWithViewControllers:`方法。而在Storyboard中,可以通过拖拽一个`Tab Bar ...

    Object-C 中将视图控制器加到UIWindow

    这是最基础且常用的方法,适用于初始化应用程序时设置根视图控制器。首先,你需要创建一个视图控制器实例,然后将其视图设置为窗口的根视图。 ```objc UIViewController *rootViewController = [[UIViewController ...

Global site tag (gtag.js) - Google Analytics