自定义后退按钮标题并保持向后滑动手势

时间:2014-05-20 17:50:58

标签: ios ios7 uinavigationcontroller uibarbuttonitem

问题: 我想在像Whatsapp(< Chats(2)/< Chats(3))这样的弹出式视图控制器中自定义导航后退按钮标题。

但是,如果您使用

,则在弹出的视图控制器中分配新的backBarButtonItem将禁用滑动后退手势
self.navigationController.interactivePopGestureRecognizer.delegate = self;

为了保持手势的正常运行,它会给你带来更多麻烦(太多bugssss)。

4 个答案:

答案 0 :(得分:1)

您必须在显示标题的self.navigationItem.backBarButtonItem之前设置ViewController属性。

在Whatsapp示例中,您必须在聊天列表视图控制器上设置标题。

类似的东西:

self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"chats(2)" style:UIBarButtonItemStylePlain target:nil action:nil];

之后,您只需设置title的{​​{1}}。

答案 1 :(得分:1)

如果你想在整个应用程序中清空后退按钮标题,其中一个解决方案是在swizzled viewDidLoad中调用viewDidLoad并清空后退按钮标题。 并且它不会影响interactivePopGestureRecognizer的工作(确保启用interactivePopGestureRecognizer)。

            @implementation UIViewController (Customizations)

            + (void)load {
                static dispatch_once_t onceToken;
                dispatch_once(&onceToken, ^{
                    [UIViewController swizzleClass:[UIViewController class] method:@"viewDidLoad"];
                });
            }

            + (void)swizzleClass:(Class)class method:(NSString*)methodName {
                SEL originalMethod = NSSelectorFromString(methodName);
                SEL newMethod = NSSelectorFromString([NSString stringWithFormat:@"%@%@", @"override_", methodName]);
                [self swizzle:class from:originalMethod to:newMethod];
            }

            + (void)swizzle:(Class)class from:(SEL)original to:(SEL)new {
                Method originalMethod = class_getInstanceMethod(class, original);
                Method newMethod = class_getInstanceMethod(class, new);
                if(class_addMethod(class, original, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
                    class_replaceMethod(class, new, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
                } else {
                    method_exchangeImplementations(originalMethod, newMethod);
                }
            }

            - (void)override_viewDidLoad {
                //Empty back button title
                UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
                [self.navigationItem setBackBarButtonItem:backButtonItem];
                [self override_viewDidLoad];
            }

            @end

答案 2 :(得分:0)

对于那些只想使用UINavigationController并修复此问题的人。我在Swift中为UINavigationController编写了一个扩展。

如果你很快刷回来,它就不会出现问题。

extension UINavigationController: UINavigationControllerDelegate, UIGestureRecognizerDelegate {

    public override static func initialize() {
        struct Static {
            static var token: dispatch_once_t = 0
        }

        if self !== UINavigationController.self {
            return
        }

        dispatch_once(&Static.token) {

            // Swizzle viewDidLoad

            self.swizzleViewDidLoad()

            // Swizzle pushViewController

            self.swizzlePushController()
        }
    }

    // MARK: - Helpers

    static func swizzleViewDidLoad() {
        let originalViewDidLoadSelector = #selector(UINavigationController.viewDidLoad)
        let swizzledViewDidLoadSelector = #selector(UINavigationController.newViewDidLoad)

        let originalViewDidLoadMethod = class_getInstanceMethod(self, originalViewDidLoadSelector)
        let swizzledViewDidLoadMethod = class_getInstanceMethod(self, swizzledViewDidLoadSelector)

        let didAddViewDidLoadMethod = class_addMethod(self, originalViewDidLoadSelector, method_getImplementation(swizzledViewDidLoadMethod), method_getTypeEncoding(swizzledViewDidLoadMethod))

        if didAddViewDidLoadMethod {
            class_replaceMethod(self, swizzledViewDidLoadSelector, method_getImplementation(originalViewDidLoadMethod), method_getTypeEncoding(swizzledViewDidLoadMethod))
        } else {
            method_exchangeImplementations(originalViewDidLoadMethod, swizzledViewDidLoadMethod);
        }
    }

    static func swizzlePushController() {
        let originalPushControllerSelector = #selector(UINavigationController.pushViewController(_:animated:))
        let swizzledPushControllerSelector = #selector(UINavigationController.newPushViewController(_:animated:))

        let originalPushControllerMethod = class_getInstanceMethod(self, originalPushControllerSelector)
        let swizzledPushControllerMethod = class_getInstanceMethod(self, swizzledPushControllerSelector)

        let didAddPushControllerMethod = class_addMethod(self, originalPushControllerSelector, method_getImplementation(swizzledPushControllerMethod), method_getTypeEncoding(swizzledPushControllerMethod))

        if didAddPushControllerMethod {
            class_replaceMethod(self, swizzledPushControllerSelector, method_getImplementation(originalPushControllerMethod), method_getTypeEncoding(swizzledPushControllerMethod))
        } else {
            method_exchangeImplementations(originalPushControllerMethod, swizzledPushControllerMethod);
        }
    }

    // MARK: - Method Swizzling

    func newViewDidLoad() {
        self.newViewDidLoad()

        self.interactivePopGestureRecognizer?.delegate = self
        self.delegate = self
    }

    func newPushViewController(viewController: UIViewController, animated: Bool) {
        self.interactivePopGestureRecognizer?.enabled = false

        self.newPushViewController(viewController, animated: animated)
    }

    // MARK: - UINavigationControllerDelegate

    public func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
        self.interactivePopGestureRecognizer?.enabled = true
    }
}

答案 3 :(得分:-1)

答案:

花了一天时间来解决这个问题,我有一个非常简单易用的解决方案,适用于iOS 6& iOS 7:

1)。 AppDelegate中的自定义样式(颜色,字体)(假设您将对所有控制器使用相同的样式)

2)。像这样创建一个自定义UINavigationController:

CustomBackNavigationController.h

@interface CustomBackNavigationController : UINavigationController <UINavigationControllerDelegate>

@property (nonatomic, strong) UIBarButtonItem *backButton;

@end

CustomBackNavigationController.m

@implementation CustomBackNavigationController

@synthesize backButton;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.delegate = self;
}


- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    backButton = [[UIBarButtonItem alloc] initWithTitle:@"Chats" style:UIBarButtonItemStyleBordered target:nil action:nil];
    viewController.navigationItem.backBarButtonItem = backButton;
}

@end
在弹出的视图控制器中,只需像这样更改backButton标题

- (void)someMethod
{
    CustomBackNavigationController *customBackNavigationController = (CustomBackNavigationController *) self.navigationController;

    [customBackNavigationController.backButton setTitle:@"Chats (1)"];
}

那就是它!