viewWillDisappear:View Controllerがポップされているか、サブView Controllerを表示しているかを判断します

StackOverflow https://stackoverflow.com/questions/1816614

質問

この問題の良い解決策を見つけるのに苦労しています。 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];
}

Swift:

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   削除またはポップされたために消えているかどうかを確認できます   viewWillDisappear:メソッドで自身を確認することにより、   式([self isBeingDismissed] || [self   isMovingFromParentViewController])。"

     

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

ビューがポップされているかどうかだけを知りたい場合、 viewDidDisappear self.navigationController nil であることがわかりました。コントローラのスタックから削除されます。これは簡単な代替テストです。

(これは他のあらゆる種類のゆがみを試した後に発見しました。ポップ時に通知されるView Controllerを登録するNavigation Controllerプロトコルがないことに驚いています。 UINavigationControllerDelegate は使用できません。実際に実際の表示作業を行います。)

Swift 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 に適用されますが、他の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
    }
}

あなたは、スタックにプッシュされたと言ったときに新しいビューをプッシュすることにより、ビューがNavigation Controllerのスタックの下に移動していることを意味すると仮定します。 viewDidUnload メソッドを使用して NSLog ステートメントを追加し、コンソールに何かを書き込むことをお勧めします。 NSLog から viewWillDissappeer へ。

これは、sbrocketの答えと同じことを達成するためのカテゴリです:

ヘッダー:

#import <UIKit/UIKit.h>

@interface UIViewController (isBeingPopped)

- (BOOL) isBeingPopped;

@end

出典:

#import "UIViewController+isBeingPopped.h"

@implementation UIViewController (isBeingPopped)

- (BOOL) isBeingPopped {
    NSArray *viewControllers = self.navigationController.viewControllers;
    if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
        return NO;
    } else if ([viewControllers indexOfObject:self] == NSNotFound) {
        return YES;
    }
    return NO;
}

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