【问题标题】:iphone navigationController : wait for uialertview response before to quit the current viewiphone navigationController:在退出当前视图之前等待 uialertview 响应
【发布时间】:2010-11-26 15:56:16
【问题描述】:

我有一个带有导航控制器管理的后退按钮的视图,我想检查当用户单击后退按钮时文件是否已保存。 如果文件已保存,则返回上一个视图,否则 uialertview 会询问您是否要保存文件。

所以我这样做了,但视图消失了,之后出现了警报视图。

-(void)viewWillDisappear:(BOOL)animated {
if(!self.fileSaved){
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Save the file?"  delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes",nil];
    [alert show];
    [alert release];
}
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
switch (buttonIndex) {
    case 0:
        NSLog(@"NO");
        break;
    case 1:
        NSLog(@"yes");
        break;
    default:
        break;
}
}

【问题讨论】:

    标签: iphone objective-c uinavigationcontroller uialertview


    【解决方案1】:

    当 viewWillDisappear 被调用时,已经太晚了。您应该更早地拦截后退按钮。我从未这样做过,但我的建议是在您的 viewDidAppear 方法中的 navigationBar 属性上设置委托:

    // save the previous delegate (create an ivar for that)
    prevNavigationBarDelegate = self.navigationController.navigationBar.delegate;
    
    self.navigationController.navigationBar.delegate = self;
    

    不要忘记在 viewWillDisappear 中重新设置它:

    self.navigationController.navigationBar.delegate = prevNavigationBarDelegate;
    

    然后拦截 shouldPopItem 方法:

    - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
         if(!self.fileSaved) {
             UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Save the file?"  delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes",nil];
             [alert show];
             [alert release];
    
             return NO;
         }
    
       if ([prevNavigationBarDelegate respondsToSelector:@selector(navigationBar:shouldPopItem:)]) 
          return [prevNavigationBarDelegate navigationBar:navigationBar shouldPopItem:item];
    
       return YES; 
    }
    

    并在对话框的 YES 处理程序中,手动弹出控制器:

    [self.navigationController popViewController:YES];
    

    【讨论】:

    • 听起来合乎逻辑,但您可能应该在覆盖之前保存当前导航栏委托,在您决定弹出自己之后重置它,甚至可以通过 navigationBar:shouldPopItem: 调用旧委托(如果不是 nil)在显示警报之前。
    • @Mathieu:是否调用了 shouldPopItem 方法?如果没有,您可能必须在 viewDidAppear 方法而不是 init 方法中设置委托。 pix0r 的评论也是有效的。我会更新我的答案以反映这一点。
    • 如果我在 viewDidAppear 或 viewDidLoad 或 init 方法中设置委托,则不会调用 shouldPopItem
    • 这是一个问题,因为您无法更改“由导航控制器创建并由该对象管理”的导航栏的委托(根据 Apple 文档)。
    • 似乎通常 UINavigationController 是 UINavigationBar 的委托,因此您可以继承 UINavigationController 并在那里覆盖此方法。在实践中,我在针对 super 调用此方法时确实收到了警告(警告:super 可能不会对此做出响应),但它确实有效。
    【解决方案2】:

    您必须继承 UINavigationController 才能使其工作。然后覆盖 - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item 。 您应该设置您的视图控制器采用的自定义 Delegate 协议,如果您允许它弹出,请调用您的 [super navigationBar shouldPopItem:],否则,返回 NO 到上述方法。

    【讨论】:

    • 我已经实现了这个并且可以验证它确实有效,并且在我看来是完成这个的最干净的方法。
    【解决方案3】:

    像下面这样添加一个左键项不是更容易吗:

    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveThisDate)];
    self.navigationItem.leftBarButtonItem = backButton;
    [backButton release];
    

    【讨论】:

    • 我尝试了其他帖子中的所有其他复杂内容,但这个工作就像一个魅力,没有复杂性。
    • 同样。如果您有一个正在使用的导航控制器,并且希望您的操作仅针对特定的视图控制器完成,我相信这是唯一的方法。
    【解决方案4】:

    要跟进 nobre 响应,正如 Jon 提到的那样,最好的方法是子类化 UINavigationController。

    实现这一目标的最简单和最快的方法:

    1. 在 Interface Builder 中修改导航控制器的类以从 CustomNavigationControllerDelegate 继承

    1. 在您的 UIViewController 中实现 CustomNavigationControllerDelegate 协议

    @interface YourViewController <CustomNavigationControllerDelegate>

    #pragma mark - UINavigationBar Delegate Methods
    - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
    
        UIAlertView* alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancel otherButtonTitles:ok, nil];
        alert.tag = kpopup_back;
        [alert show];
    
        return NO;
    }
    
    1. 将您的控制器注册为委托

    #pragma mark - viewWillAppear - (void) viewWillAppear:(BOOL)animated { ((CustomNavigationController*)self.navigationController).customDelegate = self; }

    1. 最后也是重要的部分,删除委托(以避免在弹出时重新触发自己)并自己在 UIAlertViewDelegate 中弹出控制器

    case kpopup_back : { if(buttonIndex != 0) //OK { ((CustomNavigationController*)self.navigationController).customDelegate = nil; [self.navigationController popViewControllerAnimated:YES]; } } break;

    它对我来说完美无缺,希望它可以提供帮助。


    以下是来源:

    CustomNavigationControllerDelegate.h

    #import <UIKit/UIKit.h>
    
    @protocol CustomNavigationControllerDelegate <NSObject>
    @optional
    - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;
    @end
    
    @interface CustomNavigationController : UINavigationController
    
    @property (nonatomic, retain) id<CustomNavigationControllerDelegate> customDelegate;
    
    @end
    

    CustomNavigationControllerDelegate.m

    #import "CustomNavigationController.h"
    
    @interface CustomNavigationController ()
    
    @end
    
    @implementation CustomNavigationController
    
    - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
    
        if (_customDelegate && [_customDelegate respondsToSelector:@selector(navigationBar:shouldPopItem:)]) {
            return [_customDelegate navigationBar:navigationBar shouldPopItem:item];
        }
    
        return YES;
    }
    
    @end
    

    【讨论】:

      猜你喜欢
      • 2021-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-17
      • 2022-12-20
      • 2018-03-25
      • 1970-01-01
      • 2023-01-17
      相关资源
      最近更新 更多