自定义后退按钮标题并保持向后滑动手势
问题:我想在弹出的视图控制器中自定义导航后退按钮标题,如Whatsapp(<Chats(2)/ <Chats(3))。
但是,如果您使用弹出视图控制器中的新backBarButtonItem将禁用滑动后退手势
self.navigationController.interactivePopGestureRecognizer.delegate = self;
为了保持手势的有效,它会给你带来更多麻烦(太多bugssss)。
您必须在ViewController
上设置self.navigationItem.backBarButtonItem
属性,该属性将在显示标题之前出现。
在Whatsapp示例中,您必须在聊天列表视图控制器上设置标题。
像这样的东西:
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"chats(2)" style:UIBarButtonItemStylePlain target:nil action:nil];
之后,您可以只设置self.navigationItem.backBarButtonItem
的title
。
如果你想在整个应用程序中清空后退按钮标题,其中一个解决方案是在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
对于那些只想使用UINavigationController并修复此问题的人。 我在Swift中为UINavigationController编写了一个Extension。
它没有问题,如果您快速刷回堆栈可能会被打破。
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 } }
回答:
花了一天时间来解决这个问题,我有一个非常简单易用的解决方案,适用于iOS 6和iOS 7:
1)。 AppDelegate中的自定义样式(颜色,字体)(假设您将对所有控制器使用相同的样式)
2)。 像这样创建一个自定义UINavigationController:
CustomBackNavigationController.h
@interface CustomBackNavigationController : UINavigationController @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)"]; }
而已 !
- 默认的UISwitch为YES,然后用NSUserDefaults保存状态
- 在UIButton中添加一个图像作为附件
- 无法用XCode / Obj-C编译Cocoapods – “Pods-prefix.pch.dia:没有这样的文件或目录”
- 故事板非法配置iOS 7
- Googleredirect,Google Drive,iOS SDK太多
- iOS:带边框的圆angular矩形出血颜色
- iOS发行版 – 参数在itms-services协议链接为plist
- iPhone – 内存泄漏 – NSData dataWithContentsOfUrl&UIWebView
- 核心图像 – 在CMSampleBufferRef上渲染一个透明的图像会导致它周围的黑框