Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone viewDidLoad在启动时在rootViewController上被调用两次_Iphone_Cocoa Touch_Uiviewcontroller_Viewdidload - Fatal编程技术网

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的间接递归,在我的跟踪中有x2
viewDidLoad
条目

我认为x2
viewDidLoad
没有任何有效的理由,因为它是一个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
}