largetitles uiscrollview不支持多个实现_scrollviewWillendDraggingWit



我在应用程序中使用以下代码实现了大型标题:

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的每个子类中启用/禁用大型标题,以免同时使用大型标题。在viewWillAppearviewWillDisappear方法中,做到这一点的好地方

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
}

最新更新