我在应用程序中使用以下代码实现了大型标题:
if #available(iOS 11.0, *) {
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .always
} else {
// Fallback on earlier versions
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y <= 0 {
if #available(iOS 11.0, *) {
self.navigationItem.largeTitleDisplayMode = .always
} else {
// Fallback on earlier versions
}
} else {
if #available(iOS 11.0, *) {
self.navigationItem.largeTitleDisplayMode = .never
} else {
// Fallback on earlier versions
}
}
self.navigationController?.navigationBar.setNeedsLayout()
self.view.setNeedsLayout()
UIView.animate(withDuration: 0.01, animations: {
self.navigationController?.navigationBar.layoutIfNeeded()
self.view.layoutIfNeeded()
})
}
我能够成功地在塔巴尔上的视图之间切换,但是当我推开塔巴尔控制器的视图时,然后使用此代码将其弹出:
_ = self.navigationController?.popViewController(animated: true)
再次在塔巴尔上的视图之间切换时,我会崩溃:由于未知的例外" nsinternalinconsistencyException",终止应用程序,原因:'错误:UISCROLLVIEW不支持多个观察者实现_scrollviewWillendEndDraggingWithVelocity:targetContentOffset:'
这不是解决方案,而是您需要在代码中调查的潜在内容。我收到了相同的错误消息(UISCrollView不支持多个实现_scrollViewWillEndDraggingWithVelocity:targetContentOffset
的观察者),并且我注意到我在做不正确的事情。我使用NavigationView在SwiftUi应用中收到了此错误消息。
我犯的错误是ParentView在根上有一个导航视图。使用导航链接我正在移动到ChildView,该链接也将导航视图作为根。这是代码中的外观:
import SwiftUI
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ParentView()
}
}
}
struct ParentView: View {
var body: some View {
NavigationView {
List {
NavigationLink(destination: ChildView()) {
Text("Parent view")
}
}
.navigationTitle("Parent")
}
}
}
struct ChildView: View {
var body: some View {
List {
ForEach(0 ..< 5) { _ in
Text("Child view")
}
}
.navigationTitle("Child")
}
}
最初这就是ChildView
的样子:
struct ChildView: View {
var body: some View {
NavigationView {
List {
ForEach(0 ..< 5) { _ in
Text("Second screen")
}
}
.navigationTitle("Second")
}
}
}
请注意,我如何尝试将视图本身嵌入到导航视图中。如第一个片段中所示,将其删除,以照顾错误消息。您可以尝试调查,也许您只是在Uikit而不是Swiftui中犯了同样的错误。
我找到了解决方案。您必须将第一个导航控制器设置为不使用大型标题。
关键是,现在UISCrollView只有一个观察者(navigationcontroller)实现_scrollviewWillendDraggingWithVelocity。
if (@available(iOS 11.0, *)) {
self.navigationController.navigationBar.prefersLargeTitles = FALSE;
self.navigationController.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeNever;
}
当我转到另一个视图时,问题视图仍在滚动时发生的问题。我通过在ScrollViewDidsCroll中设置Bool来解决问题,该scrollViewDidsCroll会在启动SEGUE时禁用任何滚动。
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if viewIsVisible {
if scrollView.contentOffset.y <= 0 {
if #available(iOS 11.0, *) {
self.navigationItem.largeTitleDisplayMode = .always
} else {
// Fallback on earlier versions
}
} else {
if #available(iOS 11.0, *) {
self.navigationItem.largeTitleDisplayMode = .never
} else {
// Fallback on earlier versions
}
}
self.navigationController?.navigationBar.setNeedsLayout()
self.view.setNeedsLayout()
UIView.animate(withDuration: 0.01, animations: {
self.navigationController?.navigationBar.layoutIfNeeded()
self.view.layoutIfNeeded()
})
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
self.viewIsVisible = false
}
我有同样的问题,我通过从 AppDelegate
中删除此行来修复它:
UINavigationBar.appearance().prefersLargeTitles = true
并在某些UIViewController
中的viewDidLoad
内部处理prefersLargeTitles
我认为上述所有答案并没有真正解决问题,并且被过度复杂化。我建议您在UIViewController
的每个子类中启用/禁用大型标题,以免同时使用大型标题。在viewWillAppear
和viewWillDisappear
方法中,做到这一点的好地方
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.largeTitleDisplayMode = .always
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.prefersLargeTitles = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.navigationBar.prefersLargeTitles = false
}