Iphone viewDidLoad在启动时在rootViewController上被调用两次
有人知道为什么这个根Iphone viewDidLoad在启动时在rootViewController上被调用两次,iphone,cocoa-touch,uiviewcontroller,viewdidload,Iphone,Cocoa Touch,Uiviewcontroller,Viewdidload,有人知道为什么这个根视图控制器的viewdiload在启动时被调用了两次吗?它快把我逼疯了 这是从第一次到查看加载的堆栈跟踪: #0 0x0000276a in -[RootViewController viewDidLoad] at RootViewController.m:71 #1 0x3097548f in -[UIViewController view] #2 0x00002734 in -[RootViewController initWithCoder:] at RootVi
视图控制器的
viewdiload
在启动时被调用了两次吗?它快把我逼疯了
这是从第一次到查看加载的堆栈跟踪:
#0 0x0000276a in -[RootViewController viewDidLoad] at RootViewController.m:71
#1 0x3097548f in -[UIViewController view]
#2 0x00002734 in -[RootViewController initWithCoder:] at RootViewController.m:39
#3 0x30ab5ce4 in -[UIClassSwapper initWithCoder:]
#4 0x30514636 in _decodeObjectBinary
#5 0x30514035 in _decodeObject
#6 0x30ab5a1d in -[UIRuntimeConnection initWithCoder:]
#7 0x30514636 in _decodeObjectBinary
#8 0x30515f27 in -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:]
#9 0x305163b0 in -[NSArray(NSArray) initWithCoder:]
#10 0x30514636 in _decodeObjectBinary
#11 0x30514035 in _decodeObject
#12 0x30ab4dde in -[UINib instantiateWithOptions:owner:loadingResourcesFromBundle:]
#13 0x30ab6eb3 in -[NSBundle(NSBundleAdditions) loadNibNamed:owner:options:]
#14 0x308f85f1 in -[UIApplication _loadMainNibFile]
#15 0x30901a15 in -[UIApplication _runWithURL:sourceBundleID:]
#16 0x308fef33 in -[UIApplication handleEvent:withNewEvent:]
#17 0x308fad82 in -[UIApplication sendEvent:]
#18 0x309013e1 in _UIApplicationHandleEvent
#19 0x32046375 in PurpleEventCallback
#20 0x30245560 in CFRunLoopRunSpecific
#21 0x30244628 in CFRunLoopRunInMode
#22 0x308f930d in -[UIApplication _run]
#23 0x309021ee in UIApplicationMain
#24 0x000022e4 in main at main.m:14
第二次:
#0 0x0000276a in -[RootViewController viewDidLoad] at RootViewController.m:71
#1 0x30ab50cd in -[UINib instantiateWithOptions:owner:loadingResourcesFromBundle:]
#2 0x30ab6eb3 in -[NSBundle(NSBundleAdditions) loadNibNamed:owner:options:]
#3 0x308f85f1 in -[UIApplication _loadMainNibFile]
#4 0x30901a15 in -[UIApplication _runWithURL:sourceBundleID:]
#5 0x308fef33 in -[UIApplication handleEvent:withNewEvent:]
#6 0x308fad82 in -[UIApplication sendEvent:]
#7 0x309013e1 in _UIApplicationHandleEvent
#8 0x32046375 in PurpleEventCallback
#9 0x30245560 in CFRunLoopRunSpecific
#10 0x30244628 in CFRunLoopRunInMode
#11 0x308f930d in -[UIApplication _run]
#12 0x309021ee in UIApplicationMain
#13 0x000022e4 in main at main.m:14
奇怪。我还没有看到这种特殊情况,但一般来说,您应该假设可以多次调用viewDidLoad。每当加载引用该控制器的nib文件时,就会调用它
对于一个只有一个笔尖的简单应用程序,这是不应该发生的。但是在一个可以加载和卸载视图控制器的更复杂的应用程序中,这种情况总是会发生。你不能假设viewDidLoad只会被调用一次。如果您正在初始化对象并希望得到保证,请在init方法中或从awakeFromNib方法的nib文件加载时进行初始化。我进行了一些调试,下面是关于
ViewController
加载顺序的发现:
initWithNibName:bundle: self = <original instance>, retainedOutlet = 0x0
loadView >>> self = <original instance>, retainedOutlet = 0x0
initWithCoder: self = <coder instance>, retainedOutlet = 0x0
initWithCoder: self = <coder instance>, retainedOutlet = 0x0
setView: self = <original instance>, retainedOutlet = 0x0
setRetainedOutlet: self = <original instance>, retainedOutlet = 0x1613c40
viewDidLoad self = <coder instance>, retainedOutlet = 0x0
awakeFromNib self = <coder instance>, retainedOutlet = 0x0
loadView <<<
viewDidLoad self = <original instance>, retainedOutlet = 0x1613c40
viewWillAppear: self = <original instance>, retainedOutlet = 0x1613c40
dealloc self = <coder instance>, retainedOutlet = 0x0
viewDidAppear: self = <original instance>, retainedOutlet = 0x1613c40
initWithNibName:bundle:self=,retainedOutlet=0x0
加载视图>>>自=,保留默认值=0x0
initWithCoder:self=,retainedOutlet=0x0
initWithCoder:self=,retainedOutlet=0x0
setView:self=,retainedOutlet=0x0
setRetainedOutlet:self=,retainedOutlet=0x1613c40
viewDidLoad self=,retainedOutlet=0x0
awakeFromNib self=,retainedOutlet=0x0
loadView我也有类似的问题,这是重命名我的XIB文件及其ViewController
类(文件所有者)的结果。不要这样做——因为它确实在XML中错误地定义了视图和委托,并且它是不可恢复的。同时,我有一个关于加载原始VC的参考,它应该是我的新VC。我相信这会导致父对象重新创建自己,然后我真的尝试调用VC。基本上,我创建了一个到VC的间接递归,在我的跟踪中有x2viewDidLoad
条目
我认为x2viewDidLoad
没有任何有效的理由,因为它是一个genesis,可以用错误的假定前提条件调用其他初始化。每次我看到x2 viewDidLoad时,我都会犯一个编码错误——经常是在我重构和移动VC类时
如果在viewDidLoad
电话中有超过的有效原因,请找人(Apple开发人员,你在听吗)从技术上详细解释一下——我已经寻找这个答案好几个月了。我遇到了与从头开始重新设计ViewController
以摆脱XIB文件并使类可重用相同的问题。我有第二个ViewController
实例,它将接收一条viewDidLoad
消息,然后是一条dealloc消息
我发现这是loadView
方法没有在ViewController
中重新定义的结果。默认的loadView
名为awakeFromNib
,将nibName
属性设置为类名。尽管我已经从项目中删除了XIB文件,但它仍然在模拟器的应用程序目录中
因此,即使您可以重置模拟器的内容和设置,以摆脱第二个viewdiload
,但更好的方法可能是重新定义loadView
,如下所示:
- (void)loadView {
self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
self.view.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
}
如果您考虑“<代码> UIViewController的< /Cord>View属性:
文档,这是有意义的”。
如果您访问此属性及其
值当前为零,视图
控制器自动调用
loadView
方法并返回
结果视图。默认的loadView
方法尝试从中加载视图
与视图关联的nib文件
控制器(如有)。如果你的观点
控制器没有关联的
nib文件,您应该覆盖
loadView
方法并使用它创建
根视图及其所有子视图
当我的应用程序第一次启动时,我也遇到了同样的问题。我发现在MainWindow.xib文件中,我将我的应用程序代理的viewController
outlet和我的窗口的rootViewController
outlet设置为我的根视图控制器。在Xcode中构建基于视图的项目文件时,应用程序代理的didfishlaunchingwithoptions
将预先填充以下内容:
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
我相信self.viewController
ivar是在调用didfishlaunchingwithoptions
之前从MainWindow.xib实例化的。然后,上面预填充的代码设置窗口的rootViewController
。因此,如果同时在MainWindow.xib文件中为该窗口指定rootViewController
outlet,实际上,您的根视图控制器将创建两次,并作为窗口的根视图控制器添加两次。当我使用xibs构建视图将一个项目从情节提要合并到旧方法时,我就遇到了这种情况。切换回去的主要原因是我无法正确地设置模态视图。我通常的做法是让UIButton中的委托方法构造某个viewcontroller的实例,设置它的一些属性(最重要的属性是委托,这样我就可以再次正确地解除模态视图控制器),然后以模态方式呈现它。在新的故事板方式中,这应该是通过一个segue来完成的。定制转换只能通过创建扩展UIStoryboardSegue类的自定义类来实现。我觉得这种方式与过去的简单方式相比太麻烦了,所以我合并了回去
这是如何导致我两次加载viewcontroller的?将代码从故事板项目传输到xib项目时,我制作了两个xib(每个ViewController一个),并复制了
-(void) setSomeProperty:(UIColor*) someColor
{
_someColor = someColor;
if(self.isViewLoaded) {
// self.view causes view creation and invokes 'viewDidLoad' then the view is not ready yet.
self.view.backgroundColor = someColor;
}
}
-(void) viewDidLoad
{
[super viewDidLoad]
if(_someColor){
self.view.backgroundColor = _someColor;
}
}
func sceneDidBecomeActive(_ scene: UIScene) {
ViewController().view.frame.origin.x = 100
}