笔者一般在 ViewController 的 viewWillAppear 中处理导航条的 UI 变化。比如是否隐藏导航栏、改变状态栏颜色等。但是最近发现在 viewWillAppear 中改变 navigationBar 的 titleTextAttributes
属性却在 pop 时出现了问题:「 从 SecondViewController 点击导航栏返回到 FirstViewController 时并没有生效,而使用滑动手势返回却可以生效。」
import UIKit
class FirstViewController: UIViewController {
...
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavgationBarTitleTextAttributes(
color: .nav_purple,
font: .nav_regular
)
}
...
}
在 iOS 系统 10 以后,UIKit 已经更新,统一后台管理 UINavigationBar,UITabBar 和 UIToolbar。特别是,对这些视图的背景属性(例如背景或阴影图像或设置条形样式)的更改可能会启动条形码的布局传递以解析新的背景外观。特别地,这意味着,试图改变的内部这些条的背景外观
layoutSubviews,
-[UIView updateConstraints] ,
viewWillLayoutSubviews,
viewDidLayoutSubviews,
updateViewConstraints
// NavBarTitleChangeable.swift
import UIKit
public protocol NavBarTitleChangeable: class {
var preferrdTextAttributes: [NSAttributedStringKey: AnyObject] { get }
}
...
// Custom UINavigationController
import UIKit
class FunNavigationViewController: UINavigationController {
private var topViewControllerNavBarTitleAttributes: [NSAttributedStringKey: AnyObject]? {
return (topViewController as? NavBarTitleChangeable)?.preferrdTextAttributes
}
private func setNavBarTitleAttributes(_ attributes: [NSAttributedStringKey: AnyObject]) {
navigationBar.titleTextAttributes = attributes
}
override func viewDidLoad() {
super.viewDidLoad()
if let attributes = topViewControllerNavBarTitleAttributes {
setNavBarTitleAttributes(attributes)
}
}
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
super.pushViewController(viewController, animated: animated)
if let attributes = topViewControllerNavBarTitleAttributes {
setNavBarTitleAttributes(attributes)
}
}
override func popViewController(animated: Bool) -> UIViewController? {
let popViewController = super.popViewController(animated: animated)
if let attributes = topViewControllerNavBarTitleAttributes {
setNavBarTitleAttributes(attributes)
}
transitionCoordinator?.animate(alongsideTransition: nil) { [weak self] _ in
if let attributes = self?.topViewControllerNavBarTitleAttributes {
self?.setNavBarTitleAttributes(attributes)
}
}
return popViewController
}
}
// MyViewController.swift
import UIKit
class FirstViewController: UIViewController, NavBarTitleChangeable {
var preferrdTextAttributes: [NSAttributedStringKey : AnyObject] {
let item = FunNavTitleTextAttributesItem(color: .nav_purple, font: .nav_regular)
return getNavgationBarTitleTextAttributes(with: item)
}
...
}