この問題の良い解決策を見つけるのに苦労しています。 View Controllerの-viewWillDisappear:
メソッドでは、View ControllerがNavigation Controllerのスタックにプッシュされているためか、ポップされているためView Controllerが消えているためかを判断する方法を見つける必要があります。
現時点では、isShowingChildViewController
などのフラグを設定していますが、かなり複雑になっています。検出できると思う唯一の方法は、-dealloc
メソッドです。
以下を使用できます。
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSArray *viewControllers = self.navigationController.viewControllers;
if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
// View is disappearing because a new view controller was pushed onto the stack
NSLog(@"New view controller was pushed");
} else if ([viewControllers indexOfObject:self] == NSNotFound) {
// View is disappearing because it was popped from the stack
NSLog(@"View controller was popped");
}
}
もちろん、これは、viewWillDisappearが呼び出されるまでにUINavigationControllerのView Controllerスタック(viewControllersプロパティを介して公開される)が更新されているために可能です。
私は最も簡単な方法だと思う:
- (void)viewWillDisappear:(BOOL)animated
{
if ([self isMovingFromParentViewController])
{
NSLog(@"View controller was popped");
}
else
{
NSLog(@"New view controller was pushed");
}
[super viewWillDisappear:animated];
}
迅速:
override func viewWillDisappear(animated: Bool)
{
if isMovingFromParentViewController
{
print("View controller was popped")
}
else
{
print("New view controller was pushed")
}
super.viewWillDisappear(animated)
}
UIViewController.hのAppleのドキュメントから:
「これらの4つのメソッドは、View Controllerの外観コールバックで使用して、子View Controllerとして表示、破棄、追加または削除されているかどうかを判断できます。たとえば、View Controllerは、式([self isBeingDismissed] || [self isMovingFromParentViewController])をチェックすることで、viewWillDisappear:メソッドで自身に尋ねることによってポップされます。 "
- (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0);
- (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0);
- (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0);
- (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0);
そう、これを行う唯一の文書化された方法は次の方法です:
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if ([self isBeingDismissed] || [self isMovingFromParentViewController]) {
}
}
Swift 3バージョン:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if self.isBeingDismissed || self.isMovingFromParentViewController {
}
}
ビューがポップされているかどうかだけを知りたい場合、コントローラのスタックから削除されたときに、self.navigationController
がnil
のviewDidDisappear
であることがわかりました。したがって、これは簡単な代替テストです。
(これは、他のあらゆる種類のゆがみを試した後に発見しました。ポップ時に通知されるView Controllerを登録するNavigation Controllerプロトコルがないことに驚いています。実際に表示作業を行うため、UINavigationControllerDelegate
を使用できません。)
スイフト4
override func viewWillDisappear(_ animated: Bool)
{
super.viewWillDisappear(animated)
if self.isMovingFromParent
{
//View Controller Popped
}
else
{
//New view controller pushed
}
}
Swiftの場合:
override func viewWillDisappear(animated: Bool) {
if let navigationController = self.navigationController {
if !contains(navigationController.viewControllers as! Array<UIViewController>, self) {
}
}
super.viewWillDisappear(animated)
}
これに関するAppleのドキュメントは理解しにくいと思います。この拡張機能は、各ナビゲーションで状態を確認するのに役立ちます。
extension UIViewController {
public func printTransitionStates() {
print("isBeingPresented=\(isBeingPresented)")
print("isBeingDismissed=\(isBeingDismissed)")
print("isMovingToParentViewController=\(isMovingToParentViewController)")
print("isMovingFromParentViewController=\(isMovingFromParentViewController)")
}
}
この質問はかなり古いですが、偶然見たので、ベストプラクティスを投稿したいです(afaik)
あなたはただできる
if([self.navigationController.viewControllers indexOfObject:self]==NSNotFound)
// view controller popped
}
これは、iOS7に適用されますが、他に適用されるかどうかはわかりません。私が知っていることから、viewDidDisappear
のビューはすでにポップされています。つまり、self.navigationController.viewControllers
をクエリすると、nil
が取得されます。したがって、それがnilかどうかを確認してください。
TL; DR
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
if (self.navigationController.viewControllers == nil) {
// It has been popped!
NSLog(@"Popped and Gone");
}
}
セグエは、iOS 6以降でこの問題を処理する非常に効果的な方法です。 Interface Builderで特定のセグエに識別子を指定した場合、prepareForSegue
で確認できます。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"LoginSegue"]) {
NSLog(@"Push");
// Do something specific here, or set a BOOL indicating
// a Push has occurred that will be checked later
}
}
@Bryan Henryに感謝、まだSwift 5で動作します
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let controllers = navigationController?.children{
if controllers.count > 1, controllers[controllers.count - 2] == self{
// View is disappearing because a new view controller was pushed onto the stack
print("New view controller was pushed")
}
else if controllers.firstIndex(of: self) == nil{
// View is disappearing because it was popped from the stack
print("View controller was popped")
}
}
}