LargeTitles UIScrollView does not support multiple observers implementing _scrollViewWillEndDraggingWithVelocity:targetContentOffset

前端 未结 5 2395
执笔经年
执笔经年 2021-02-20 09:15

I have implemented large titles in my app with the following code:

if #available(iOS 11.0, *) {
            navigationController?.navigationBar.prefersLargeTitle         


        
相关标签:
5条回答
  • 2021-02-20 09:36

    I think all of above answers don't really solve the issue and are overcomplicated. I recommend enabling/disabling large titles in each of your UIViewController's subclasses, so they don't use large titles at the same time. Good place to do it is in the viewWillAppear and viewWillDisappear methods

    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
    }
    
    0 讨论(0)
  • 2021-02-20 09:40

    I've the same problem and I fixed it by removing this line from AppDelegate:

    UINavigationBar.appearance().prefersLargeTitles = true
    

    and handle prefersLargeTitles inside viewDidLoad in certain UIViewController

    0 讨论(0)
  • 2021-02-20 09:45

    This is not a solution, but a potential thing that you need to investigate in your code. I got this same error message (UIScrollView does not support multiple observers implementing _scrollViewWillEndDraggingWithVelocity:targetContentOffset) and I noticed I was doing something incorrectly. I got this error message in a SwiftUI app using NavigationView.

    The mistake I had made was that ParentView had a Navigation View at the root. Using a NavigationLink I was moving to ChildView, which also had a NavigationView as the root. Here's what it looked like in code:

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

    Initially this is what ChildView looked like:

    struct ChildView: View {
        var body: some View {
            NavigationView {
                List {
                    ForEach(0 ..< 5) { _ in
                        Text("Second screen")
                    }
                }
                .navigationTitle("Second")
            }
        }
    }
    

    Notice how I was trying to push a view which itself was embedded in a NavigationView. Removing it as shown in the first snippet, took care of the error messages. You can try looking into that, maybe you are doing the same mistake just in UIKit instead of SwiftUI.

    0 讨论(0)
  • 2021-02-20 09:52

    I found the solution. You have to set the first navigation controller to not use large titles.

    The point is that now UIScrollView has only one observer (navigationController) implementing _scrollViewWillEndDraggingWithVelocity.

    if (@available(iOS 11.0, *)) {
    
        self.navigationController.navigationBar.prefersLargeTitles = FALSE;
        self.navigationController.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeNever;
    
    }
    
    0 讨论(0)
  • 2021-02-20 09:54

    The problem happened when the tableview was still scrolling when I went to another view. I fixed the problem by setting a bool in the scrollViewDidScroll that disables any scrolling when the segue is started.

        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
    }
    
    0 讨论(0)
提交回复
热议问题