私は、prepareForSegueが終了した後にviewDidLoadが呼び出されるという印象を受けました。これは、ヘガーティがスタンフォードのクラスを教える方法でもあります(最近では2013年2月)。
しかし、今日初めて、prepareForSegueが終了する前にviewDidLoadが呼び出されたことに気づきました。したがって、prepareForSegueで設定していたプロパティは、destinationviewDidLoadメソッド内のdestinationViewControllerでは使用できませんでした。
これは予想される動作に反しているようです。
[〜#〜]更新[〜#〜]
何が起こっているのか理解しました。私のdestinationViewControllerには、「モデル」が更新されるたびにtableViewをリロードするカスタムセッターがありました。
DestinationViewController
- (void)setManagedObjectsArray:(NSArray *)managedObjectsArray
{
_managedObjectsArray = [managedObjectsArray copy];
[self.tableView reloadData];
}
DestinationViewControllerはUITableViewControllerのサブクラスであるため、「self.tableView」を呼び出すと、ビューが強制的に読み込まれます。 Appleのドキュメントによると、View Controllerのviewプロパティを呼び出すと、ビューが強制的に読み込まれる可能性があります。 UITableViewControllerのビューはtableViewです。
したがって、prepareForSegueでは、次の行がdestinationViewControllerのビューを強制的にロードしていました。
vc.managedObjectsArray = <custom method that returns an array>;
この問題を修正するために、destinationViewControllerのモデルのカスタムセッターを次のように変更しました。
- (void)setManagedObjectsArray:(NSArray *)managedObjectsArray
{
_managedObjectsArray = [managedObjectsArray copy];
if ([self isViewLoaded]) {
[self.tableView reloadData];
}
}
これは、tableViewが画面に表示されている場合にのみ、tableViewを再読み込みします。したがって、prepareForSegue中にビューを強制的にロードすることはありません。
このプロセスに反対する人がいたら、あなたの考えを共有してください。そうでなければ、これが誰かの長い眠れない夜を防ぐことを願っています。
私は過去に同様の混乱に遭遇しました。私が学んだ一般的な経験則は次のとおりです。
PrepareForSegueに関して学んだもう1つの教訓は、冗長な処理を回避することです。たとえば、すでにtableViewセルをストーリーボードを介してVCにセグエしている場合、tableView:didSelectRowAtIndexPathとprepareForSegueの両方を処理しようとすると、同様の競合状態が発生する可能性があります。手動のセグエを利用するか、didSelectRowAtIndexPathでの処理を中止します。
ここで何が起こったのかについて少し説明を加えたいと思いました:
ビューが表示される前にprepareForSegue
が呼び出されます
viewDidload
は、ビューに最初にアクセスしたときに呼び出されます(ビューは遅延ロードされます)。
おそらく起こったことは、view
のprepareForSegue
にアクセスして、ビューの読み込みを手動でトリガーしたことです。
通常、フローは次のとおりです。
preformSegue
prepareForSegue
ViewController
が階層に追加されますviewDidLoad
。しかし、おそらくあなたの場合に起こったことは次のとおりです。
preformSegue
prepareForSegue
prepareForSegue
で、view
にアクセスしますview
が自動的にロードされます=> viewDidLoad
が呼び出されますperformSegue
から戻るviewDidLoad
は追加されません(すでに呼び出されています)したがって、通常、view
プロパティは、ViewController
が階層に追加される前にアクセスされませんが、アクセスされる場合は、viewDidLoad
をより早くトリガーできます。
共有してくれてありがとう、私の問題を理解するのを手伝ってくれました。
私の場合、destinationViewControllerはUITabBarControllerであり、そのviewControllers配列を変更するとviewDidLoadがトリガーされます。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UITabBarController *tabBarController = segue.destinationViewController;
tabBarController.viewControllers = ...
tabBarController.something = something;
}
viewDidLoadで、something属性を設定する必要があったため、上に移動する必要がありました。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UITabBarController *tabBarController = segue.destinationViewController;
tabBarController.something = something;
tabBarController.viewControllers = ...
}
簡単な解決策は配置することです
[self.tableView reloadData];
viewWillAppear
:
動的セルでも同様の問題が発生し、選択するとモーダルが表示されました。 prepareForSegue
はdidSelect:atIndexPath
の前に実行されました。私を助けたのは、ストーリーボードで、動的セルのプロトタイプではなく、コントローラーから開始するようにセグエを再割り当てしたことです。競合状態(?)を解決し、すべてが完全に機能しています!