LargeTitles UIScrollView不支持实现_scrollViewWillEndDraggingWithVelocity的多个观察者:targetContentOffset

时间:2017-12-18 15:21:38

标签: swift uiscrollview crash navigationbar tabbar

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

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()
    })
}

我能够在标签栏上的视图之间成功切换,但是当我按下Tabbar控制器顶部的视图然后使用此代码将其弹出时:

_ = self.navigationController?.popViewController(animated: true)

当我再次在标签栏上的视图之间切换时,我遇到了这个崩溃: 由于未捕获的异常终止应用程序&#39; NSInternalInconsistencyException&#39;,原因:&#39;错误:UIScrollView不支持实现_scrollViewWillEndDraggingWithVelocity的多个观察者:targetContentOffset:&#39;

5 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,我通过从UINavigationBar.appearance().prefersLargeTitles = true

中删除此行来解决此问题
prefersLargeTitles

并在某些viewDidLoad

中处理UIViewController内的{{1}}

答案 1 :(得分:1)

我找到了解决方案。您必须将第一个导航控制器设置为不使用大标题。

问题在于,现在UIScrollView仅具有一个实现_scrollViewWillEndDraggingWithVelocity的观察者(navigationController)。

if (@available(iOS 11.0, *)) {

    self.navigationController.navigationBar.prefersLargeTitles = FALSE;
    self.navigationController.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeNever;

}

答案 2 :(得分:1)

我认为以上所有答案并不能真正解决问题,而且过于复杂。我建议在您的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
}

答案 3 :(得分:0)

当我转到另一个视图时,当tableview仍在滚动时,问题就出现了。我通过在scrollViewDidScroll中设置bool来修复问题,该bool在启动segue时禁用任何滚动。

function message_broadcast(message) {
    localStorage.removeItem('message');
    localStorage.setItem('message',message);
}

答案 4 :(得分:0)

这不是解决方案,而是您需要在代码中调查的潜在问题。我收到了同样的错误消息(UIScrollView不支持实现_scrollViewWillEndDraggingWithVelocity:targetContentOffset的多个观察者),并且我发现自己做错了什么。 我在使用NavigationView的SwiftUI应用程序中收到了此错误消息。

我犯的错误是ParentView的根有导航视图。使用NavigationLink,我转到了ChildView,它也以NavigationView为根。这是代码中的样子:

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")
        }
    }
}

注意我是如何尝试推送本身嵌入到NavigationView中的视图的。如第一个代码片段所示,将其删除,将处理错误消息。您可以尝试进行调查,也许只是在UIKit中而不是SwiftUI中,您在犯同样的错误。