[英]Trying to handle “back” navigation button action in iOS
我需要檢測用戶何時點擊導航欄上的“后退”按鈕,以便在發生這種情況時執行一些操作。 我正在嘗試手動設置對此類按鈕的操作,如下所示:
[self.navigationItem.backBarButtonItem setAction:@selector(performBackNavigation:)];
- (void)performBackNavigation:(id)sender
{
// Do operations
[self.navigationController popViewControllerAnimated:NO];
}
我首先將該代碼放在視圖控制器本身中,但我發現self.navigationItem.backBarButtonItem
似乎是nil
,所以我將相同的代碼移動到父視圖控制器,將前者推送到導航堆棧。 但我既不能讓它發揮作用。 我讀過一些關於這個問題的帖子,其中一些人說需要在父視圖控制器上設置選擇器,但對我來說它無論如何都不起作用......我做錯了什么?
謝謝
使用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];
}
或者還有另一種方法可以獲取導航返回按鈕的操作。
為后退按鈕的 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];
}
斯威夫特:
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
因為 pop 是動畫的,我想立即處理后退按鈕而不是等到過渡完成。
didMoveToParentViewController
的問題在於,一旦父視圖再次完全可見,它就會被調用,因此如果您需要在此之前執行某些任務,它將無法工作。
它不適用於驅動動畫手勢。 使用willMoveToParentViewController
效果更好。
目標-c
- (void)willMoveToParentViewController:(UIViewController *)parent{
if (parent == NULL) {
// ...
}
}
迅速
override func willMoveToParentViewController(parent: UIViewController?) {
if parent == nil {
// ...
}
}
這是dadachi的答案的Objective-C版本:
- (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
}
在 Swift 4 或更高版本中:
override func didMove(toParent parent: UIViewController?) {
if parent == nil {
//"Back pressed"
}
}
設置 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
方法。
在斯威夫特:
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
的interactivePopGestureRecognizer
是個好主意,否則手勢不會調用您的處理程序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.