質問

なぜこのルートなのか知っている人はいますか View Controller's viewDidLoad 起動時に 2 回呼び出されますか?それは私を夢中にさせます!

これが初回からのスタックトレースです viewDidLoad:

#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ファイルがロードされるたびに呼び出されますよ。

唯一のペン先を持つシンプルなアプリの場合、それは起こるべきではありません。しかし、ビューコントローラをロードし、アンロードすることができますより複雑なアプリで、これはすべての時間に発生します。

他のヒント

私は私のアプリが最初に起動したこれと同じ問題がありました。私が見つけた私MainWindow.xibファイルで、私は私のルートビューコントローラに私のアプリデリゲートのviewControllerアウトレット、と私の窓のrootViewControllerコンセントの両方を設定したということでした。あなたはXcodeでビューベースのプロジェクトファイルをビルドすると、あなたのアプリケーションデリゲートのdidFinishLaunchingWithOptionsはが事前に移入されます。

self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;

私はself.viewControllerが呼び出される前にdidFinishLaunchingWithOptionsのIVARがMainWindow.xibからインスタンス化されると信じています。次いで、上記事前設定コードは、ウィンドウのrootViewControllerを設定します。 、一緒に、あなたはMainWindow.xibファイルにWindowのrootViewController口を指定するのであれば、あなたのルートビューコントローラは、実際に2回二回作成し、ウィンドウのルートビューコントローラとして追加されます。

私はいくつかのデバッグを行なったし、ここで私は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

loadViewメソッドの間に、initWithCoder:が呼び出され、viewControllerの新しいコピーが作成されます。これは、(viewDidLoadのような)メソッドの数に渡されるものです。コピーはのdeallocの呼び出しで後で破壊されます。良いニュースは、このコピーでは、あなたは、あなたが変数を初期化する必要があるかどうかを知るためのテストとしてこれを使用する他のメソッドを呼び出し、そして最も重要なことができるようにあなたがのdealloc中にオブジェクトを解放し、破壊する必要がある場合には出口は、構成されていない保持していることです。

キー持ち帰り:本当のviewControllerは、その保持IBOutletプロパティが設定されています。あなたが複数回呼び出さなっているオーバーライドされたメソッドである場合は、ちょうどIBOutletのためのあなたの保持NULLのプロパティのいずれかを確認してください。彼らはNULLされている場合は、すぐに戻ります。

誰もが、これはこのように起こっている理由として任意の手掛かりを得たか。

このの

副作用:あなたはawakeFromNib確実に使用することはできません。

あなたはのviewDidLoadは一度だけ呼び出されると仮定することはできません。あなたがオブジェクトを初期化し、保証を希望する場合は、awakeFromNibメソッドからnibファイルからロードしているinitメソッドでは場合、またはいずれかの初期化を行います。

私は同様の問題を持っていたし、それは私のXIBファイルとそのViewControllerクラス(ファイル所有者)の名前を変更した結果でした。それをしないでください - それは本当にビューやXML内misdefinedデリゲートを持って、それが回復可能ではなかったよう。その間、私は負荷への参照私の新しいVCになるはずだった、元のVCを持っていました。私は自分自身を再作成するために親を起こし、その後、VC、私は本当に起動しようとしたと信じています。基本的に、私は私のトレースに×2 viewDidLoadエントリを持っているVCへの間接的な再帰を作成します。

私はそれが起源であると前提条件を前提と間違って他の初期設定を呼び出すことができるよう×2 viewDidLoadのための任意の有効な理由があるとは思いません。私は×2のviewDidLoadを見ているたびに、それは私の部分のコーディングエラーだった - かなり頻繁に私の周りにVCクラスをリファクタリングして動いていたとき、

viewDidLoadコールよりも多くのための正当な理由がある場合は、誰か(アップルのDevあなたが聞いている)技術的な詳細にそれを説明してください - 私は今、数ヶ月のためにその答えを探してきた。

この問題がありましたが、修正することができました。

解決:

2 回ロードされているビュー コントローラー クラスの名前を変更します。

詳細:

名前を変更し、新しい名前をまったく新しい名前にします。 ファイルの名前を変更する 二度ロードの問題は止まらない。(他の人が提案したように) 新しいプロジェクトを作成するのはやりすぎかもしれません。少なくとも、より単純な解決策を最初に試してください。宛先 VC のクラス名を変更します。

ヒント:クラスの名前を変更することで問題が解決する場合は、明らかにそのクラスへのすべての参照を更新する必要があります。プロジェクト全体の検索に Command+Shift+F を使用すると、これを高速化できます。

私はXIBファイルを取り除くためにとクラスが再利用可能にするためにゼロからViewControllerを再設計されたとして、

私は同じ問題に遭遇しました。私はのdeallocメッセージに続いてViewControllerメッセージを受け取ることになり、この二viewDidLoadのインスタンスを持っていました。

私は、これがloadViewで再定義されていないViewController方法の結果であったが分かりました。クラス名に設定loadViewプロパティでawakeFromNibと呼ばれるデフォルトのnibName、。私はプロジェクトからXIBファイルを削除していたにもかかわらず、それはシミュレータ上のアプリケーションディレクトリにまだありました。

だから、あなただけの二viewDidLoadを取り除くために、シミュレータの内容や設定をリセットできていても、より良い方法は、ちょうどこのようloadViewを再定義することがあります。

- (void)loadView {
    self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
    self.view.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin; 
}
あなたはUIViewController'sビュープロパティのドキュメントを検討する場合は、

それは理にかなっています:

  

あなたは、このプロパティにアクセスし、その場合は   値は、ビューは現在ゼロであります   コントローラが自動的に呼び出されます   loadView方法とリターン   結果の表示。デフォルトのloadView   この方法は、からビューをロードしようと   ビューに関連付けられているnibファイル   コントローラ(もしあれば)。あなたのビューの場合   コントローラは、関連を持っていません   nibファイルは、あなたがオーバーライドする必要があります   loadView方法と作成するためにそれを使用します   ルートビューとサブビューのすべてます。

私の場合、私は私が実際に二回rootViewControllerが割り当てられていることに気づきませんでした

application:didFinishLaunchingWithOptions:applicationDidBecomeActive:

これに加えて、TouchID などのシステム機能を使用している場合は、 applicationWillResignActive AppDelegate 内で呼び出しが行われ、コントローラーをセキュア ルート コントローラーにリセットすると再呼び出しされます。 PerformSegueWithIdentifier(self.MAIN_SEGUE ,送信者:自己) 発砲しません!

私はビューを構築するためxibsを使用して、古いやり方にストーリーボードからプロジェクトをマージするとき、

これは私に起こりました。スイッチバックのための主な理由は、私がきちんと正しくモーダルビューを置くことができなかったという事実でした。私は通常それを行う方法は、UIButtonからデリゲートメソッドを有することによって、特定のViewControllerのインスタンスを構築する(iは正しく再びモーダルビューコントローラを閉じることができるように、デリゲートが最もインポートもの)、そのプロパティの一部を設定し、存在していますそれモーダルな方法インチ新しいストーリーボードように、これはおそらくセグエで行われます。トランジションをカスタマイズするUIStoryboardSegueクラスを拡張するカスタムクラスを作成することによってのみ、なんとかです。私はそれは私が戻ってマージするために使用される簡単な方法と比較して、このあまりにも多くの手間を見つけます。

これはどのように私は二回のViewControllerの負荷を持たせるのですか? XIBプロジェクトにストーリーボードプロジェクトからコードを転送するとき、私はストーリーボードからxibsの対(それぞれのViewControllerに対して1つ)とのコピーするのViewControllerオブジェクトを作りました。これはそれではないVIW、しかしのViewControllerでXIBにつながりました。私は(ファイルの所有者は、またのViewControllerのインスタンスであるため)のViewControllerでのViewControllerを入れていたという意味。私はあなたがこの問題を持っていた、あなたのケースではないと思うが、私はそれは多分いつか誰かに役立ちます願っています。

これは、ビューコントローラから及びオブジェクトセクションのルートレベルにビューコントローラからビューを移動修正します。ビューコントローラとそれのナビゲーション項目の両方が削除されるべきです。ビルドして実行し、あなたは、ビューコントローラのための唯一の割り当てが表示されます。これは、ファイルの所有者である。

あなたのコードは、それがまだロードされていないビューのプロパティにアクセスした場合、ビューコントローラがちょうど空のビューを作成し、それがview did load誤ってトリガすることができるもの。

最も一般的なエラーは、初期化時にビュープロパティにアクセスしています。誤ってビューのプロパティにアクセスする必要がありXIBによって呼び出されるいくつかのプロパティアクセサ(セッター)であってもよいです。

どのような場合には、いくつかのプロパティは、あなたが見るためにいくつかの値を適用する前に、IBInspectableチェックする必要がありますisViewLoadedでアノテートされます。


-(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;
  }
}

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top