ユーザーがナビゲーションバーの「戻る」ボタンをタップしたときに、それが発生したときにいくつかの操作を実行するために検出する必要があります。私はこのようなボタンにアクションを手動で設定しようとしています:
[self.navigationItem.backBarButtonItem setAction:@selector(performBackNavigation:)];
- (void)performBackNavigation:(id)sender
{
// Do operations
[self.navigationController popViewControllerAnimated:NO];
}
最初にそのコードをView Controller自体に配置しましたが、self.navigationItem.backBarButtonItem
がnil
であるように見えたため、同じコードを親View Controllerに移動し、前者をNavigation Stackにプッシュしました。しかし、私はそれを機能させることもできません。私はこの問題に関するいくつかの投稿を読みましたが、一部の人はセレクタを親のView Controllerに設定する必要があると言っていましたが、私にとってはそれはうまくいきません...何が間違っているのでしょうか?
ありがとう
VIewWillDisappear
メソッドを使用してこのコードを試して、NavigationItemの[戻る]ボタンが押されたことを検出します。
-(void) viewWillDisappear:(BOOL)animated
{
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound)
{
// Navigation button was pressed. Do some stuff
[self.navigationController popViewControllerAnimated:NO];
}
[super viewWillDisappear:animated];
}
または、Navigation BAckボタンのアクションを取得する別の方法があります。
戻るボタンのUINavigationItemのカスタムボタンを作成します。
例:
ViewDidLoadで:
- (void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle:@"Home" style:UIBarButtonItemStyleBordered target:self action:@selector(home:)];
self.navigationItem.leftBarButtonItem=newBackButton;
}
-(void)home:(UIBarButtonItem *)sender
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
Swift:
override func willMoveToParentViewController(parent: UIViewController?)
{
if parent == nil
{
// Back btn Event handler
}
}
override func didMoveToParentViewController(parent: UIViewController?) {
if parent == nil {
//"Back pressed"
}
}
おそらく、この回答は説明ではなく質問のタイトルに合っています。 UINavigationBar
の[戻る]ボタンをタップしたタイミングを知りたい場合に便利です。
この場合、UINavigationBarDelegate
プロトコルを使用して、次のメソッドのいずれかを実装できます。
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item;
didPopItem
メソッドが呼び出されるのは、[戻る]ボタンをタップしたか、[UINavigationBar popNavigationItemAnimated:]
メソッドを使用し、ナビゲーションバーがアイテムをポップしたためです。
didPopItem
メソッドをトリガーしたアクションを知りたい場合は、フラグを使用できます。
このアプローチでは、iOSの戻るボタンに似たものにするために矢印画像付きの左バーボタン項目を手動で追加する必要がなく、カスタムターゲット/アクションを設定できます。
ページビューコントローラーとカスタムページインジケータービューを持つビューコントローラーがあります。また、カスタムUINavigationBarを使用してタイトルを表示し、自分がどのページにいるかを確認し、戻るボタンを使用して前のページに戻ります。また、ページコントローラーで前/次のページにスワイプすることもできます。
#pragma mark - UIPageViewController Delegate Methods
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
if( completed ) {
//...
if( currentIndex > lastIndex ) {
UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"Some page title"];
[[_someViewController navigationBar] pushNavigationItem:navigationItem animated:YES];
[[_someViewController pageControl] setCurrentPage:currentIndex];
} else {
_autoPop = YES; //We pop the item automatically from code.
[[_someViewController navigationBar] popNavigationItemAnimated:YES];
[[_someViewController pageControl] setCurrentPage:currentIndex];
}
}
}
そこで、UINavigationBarデリゲートメソッドを実装します。
#pragma mark - UINavigationBar Delegate Methods
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
if( !_autoPop ) {
//Pop by back button tap
} else {
//Pop from code
}
_autoPop = NO;
return YES;
}
この場合、ポップがアニメーション化され、移行が完了するまで待たずにすぐに戻るボタンを処理したいので、shouldPopItem
を使用しました。
didMoveToParentViewController
の問題は、親ビューが再び完全に表示されると呼び出されるため、その前にいくつかのタスクを実行する必要がある場合、機能しないことです。
また、ドリブンアニメーションジェスチャでは機能しません。 willMoveToParentViewController
を使用するとより効果的です。
Objective-c
- (void)willMoveToParentViewController:(UIViewController *)parent{
if (parent == NULL) {
// ...
}
}
スイフト
override func willMoveToParentViewController(parent: UIViewController?) {
if parent == nil {
// ...
}
}
これは、Objective-Cバージョンの dadachi's Answerです:
- (void)didMoveToParentViewController:(UIViewController *)parent{
if (parent == NULL) {
NSLog(@"Back Pressed");
}
}
UINavigationBarのデリゲートを設定し、次を使用します。
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
//handle the action here
}
他の解決策はどれも私にとってはうまくいきませんでしたが、これはうまくいきます:
UINavigationControllerの独自のサブクラスを作成し、UINavigationBarDelegateを実装し(ナビゲーションバーのデリゲートを手動で設定する必要はありません)、戻るボタンを押すと呼び出されるメソッドを定義するUIViewController拡張機能を追加し、UINavigationControllerサブクラスにこのメソッドを実装します:
func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
self.topViewController?.methodToBeCalledOnBackButtonPress()
self.popViewController(animated: true)
return true
}
UINavigationControllerDelegateを設定し、このデリゲートfunc(Swift)を実装します。
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
if viewController is <target class> {
//if the only way to get back - back button was pressed
}
}
UINavigationController
メソッドを実装するカスタムshouldPop
サブクラスを使用します。
Swiftの場合:
class NavigationController: UINavigationController, UINavigationBarDelegate
{
var shouldPopHandler: (() -> Bool)?
func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool
{
if let shouldPopHandler = self.shouldPopHandler, !shouldPopHandler()
{
return false
}
self.popViewController(animated: true) // Needed!
return true
}
}
設定すると、shouldPopHandler()
が呼び出され、コントローラーがポップされるかどうかが決定されます。設定されていない場合、通常どおりポップされます。
ジェスチャーはハンドラーを呼び出さないため、UINavigationController
s interactivePopGestureRecognizer
を無効にすることをお勧めします。
Swift 4以降:
override func didMove(toParent parent: UIViewController?) {
if parent == nil {
//"Back pressed"
}
}