PopViewController奇怪的行为

Ton*_*min 2 objective-c popviewcontroller ios

由于一个奇怪的请求,我试图拒绝,但它没有工作,我不得不覆盖navigationBar的后退按钮.

我已经制作了一个自定义的UINavigationController子类并且破解了该 - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item方法.

这是我的代码:

@interface CustomUINavigationController ()

@end

@implementation CustomUINavigationController


#pragma mark - UINavigationBar delegate methods

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {

    if ([[self.viewControllers lastObject] isKindOfClass:[ViewController1 class]]) {
        ViewController1 *vc1 = (ViewController1 *)[self.viewControllers lastObject];
        [vc1 handleBackAction];
        if (vc1.canPopVC == YES) { 
            [self popViewControllerAnimated:YES];
            return YES;
        } else {
            return NO;
        }
    }

    [self popViewControllerAnimated:YES];
    return YES;
}

@end
Run Code Online (Sandbox Code Playgroud)

一切正常,除非我以编程方式弹出viewController.每次我想在弹出后执行推送时,应用程序都会崩溃.转向NSZombie on,显示当以编程方式弹出viewController时,其父viewController被释放.此时,制作自定义backButton不是一个选项,因为它将丢失原生iOS 7滑动到popViewController功能.

崩溃日志:

*** -[ContactsDetailViewController performSelector:withObject:withObject:]: message sent to deallocated instance 0x1806b790
Run Code Online (Sandbox Code Playgroud)

hen*_*yaz 12

(我以前的帖子是完全错误的.这是一个完全重写的适当的解决方案.)

当我转换为ARC时,当我选择删除一些生成警告的代码时,我会弹出这种行为 - 我认为这些代码没有被调用.

情况如下:

如果navigationBar:shouldPopItem:在UINavigationController的子类中进行阴影处理,则当用户触摸NavBar的BACK按钮时,将不会弹出当前视图控制器.但是,如果popViewControllerAnimated:直接呼叫,您navigationBar:shouldPopItem:仍然会被调用,并且视图控制器将弹出.

这就是当用户触摸BACK按钮时视图控制器无法弹出的原因:

UINavigationController有一个名为的隐藏方法navigationBar:shouldPopItem:.当用户单击BACK按钮时调用此方法,并且这是popViewControllerAnimated:在用户触摸BACK按钮时通常调用的方法.

阴影时navigationBar:shouldPopItem:,不会调用超类的实现,因此不会弹出ViewController.

为什么你不应该popViewControllerAnimated:在你的子类中调用' navigationBar:shouldPopItem::

如果您popViewControllerAnimated:在内部呼叫navigationBar:shouldPopItem:,当您单击导航栏上的"返回"按钮时,您将看到所需的行为:您可以确定是否要弹出,如果需要,您的视图控制器会弹出.

但是,如果你popViewControllerAnimated:直接打电话,你最终会弹出两个视图控制器:一个来自你的直接呼叫popViewControllerAnimated:,一个来自你加入的呼叫navigationBar:shouldPopItem:.

我认为是安全的解决方案:

您的自定义导航控制器应该声明如下:

@interface CustomNavigationController : UINavigationController <UINavigationBarDelegate> 
{
    // .. any ivars you want
}
@end
Run Code Online (Sandbox Code Playgroud)

您的实现应该包含如下所示的代码:

// Required to prevent a warning for the call [super navigationBar:navigationBar shouldPopItem:item]
@interface UINavigationController () <UINavigationBarDelegate>
@end


@implementation CustomNavigationController

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
    BOOL rv = TRUE;

    if ( /* some condition to determine should NOT pop */ )
    {
        // we won't pop
        rv = FALSE;

        // extra code you might want to execute ...
    } else
    {
        // It's not documented that the super implements this method, so we're being safe
        if ([[CustomNavigationController superclass]
                instancesRespondToSelector:@selector(navigationBar:shouldPopItem:)])
        {
            // Allow the super class to do its thing, which includes popping the view controller 
            rv = [super navigationBar:navigationBar shouldPopItem:item];

        }
    }

    return rv;
}
Run Code Online (Sandbox Code Playgroud)