Список зависает после перехода по навигационной ссылке, вложенной в родительский список (только для MacCatalyst)

Проблема

Это происходит только при создании цели для MacCatalyst. Он отлично работает на айфонах (реальных устройствах и симуляторах).

Я создаю родительский список внутри NavigationView, называю его «Query View».

Каждый элемент в QueryView является NavigationLink. Одним из этих целевых представлений NavigationLink является представление, содержащее другой список (представление модели). При переходе к ModelView его список событий обычно зависает после начальной прокрутки или двух. После того, как оно зависло, единственный способ разморозить его — либо выскочить из представления, либо вернуться обратно, изменить размер окна или иногда добавить/удалить что-то из списка.

Минимально воспроизводимый пример

Ниже приведены шаги для минимального воспроизводимого примера:

  1. Новый проект Xcode с использованием интерфейса UIKit LifeCycle и SwiftUI
  2. Отметьте опцию MacCatalyst
  3. Добавить код делегата сцены
  4. Добавьте весь остальной код в один файл

Заметки

• Иногда он немного прокручивается, но в конце концов он всегда зависает.

• Загрузка ЦП после приостановки составляет 0%, но затем достигает типичного значения 15% при попытке прокрутки во время приостановки.

• Список — это единственная часть пользовательского интерфейса, которая зависает, все остальное работает.

Код делегата сцены

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        let rootVM = RootView.ViewModel()

        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: RootView(vm: rootVM))
            self.window = window
            window.makeKeyAndVisible()
        }
    }

Весь другой код


import SwiftUI

struct RootView: View {
    
    @ObservedObject var vm:ViewModel
    
    var body: some View {
        NavigationView {
            List {
                ForEach(vm.roles, id: \.rawValue) { role in
                    NavigationLink(
                        role.rawValue,
                        destination: viewForRole(role: role)
                    )
                }
            }
        }
        .navigationBarTitle("Roles")
    }
    
    @ViewBuilder func viewForRole(role: ViewModel.Role) -> some View {
        if role == .admin {
            QueryView(vm: vm.queryVM)
        }else if role == .moderator {
            Text("Coming soon!")
        }else{
            Text(role.rawValue)
        }
    }
}

extension RootView {
    
    class ViewModel:ObservableObject {
        
        let queryVM = QueryView.ViewModel()
        
        @Published var roles:[Role]
        
        enum Role:String, CaseIterable {
            case admin = "Admin"
            case moderator = "Moderator"
        }
        
        init() {
            self.roles = Role.allCases
        }
    }
}



struct QueryView:View {
    
    @ObservedObject var vm:ViewModel
    
    var body: some View {
        VStack(alignment: .center) {
            TextField("Search", text: $vm.searchValue)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .frame(maxWidth: 250)
                .padding()
            List {
                ForEach(vm.models, id: \.self) { model in
                    NavigationLink(model, destination: ModelView(vm: ModelView.ViewModel()))
                }
            }
            Button("Add Model") {
                vm.addModel()
            }
            .padding()
        }
        .navigationBarTitle("Query View")
    }
    
}

extension QueryView {
    
    class ViewModel:ObservableObject {
        
        @Published var models:[String]
        
        @Published var searchValue:String
        
        init() {
            self.searchValue = "Just for looks..."
            self.models = [String]()
            for i in 0..<20 {
                models.append("Model \(i+1)")
            }
        }
        
        
        func addModel() {
            self.models.append("Model \(models.count + 1)")
        }
    }
}

struct ModelView:View {
    
    @ObservedObject var vm:ViewModel
    
    var body: some View {
        HStack {
            List {
                ForEach(vm.events, id: \.self) { event in
                    Text(event)
                }
            }
            .frame(maxWidth: 300)
            Text("Other Model Form")
                .frame(maxWidth: .infinity)
        }
        .navigationBarTitle("Model View")
    }
}


extension ModelView {
    
    class ViewModel:ObservableObject {
        
        var events:[String]
        
        init() {
            self.events = [String]()
            for i in 0..<30 {
                events.append("Event \(i+1)")
            }
        }
    }
}

person KissTheCoder    schedule 18.01.2021    source источник
comment
Интересно, в консоли получаю [Lifecycle] Scene state change error: the scene is no longer connected. (NSMenuBarScene_9607F855-ECA8-4CF0-BB2F-DE9D09E7003B). Чтобы попытаться получить ответ, может потребоваться отчет об ошибке Apple. В качестве обходного пути я предлагаю вам придерживаться жизненного цикла приложения SwiftUI.   -  person lorem ipsum    schedule 18.01.2021
comment
@loremipsum Похоже, проблема для меня все еще не устранена. Даже при использовании жизненного цикла приложения SwiftUI я также получаю Scene state change error: the scene is no longer connected. (NSMenuBarScene_2BB9DB4D-C1E9-469B-83EB-41DADCE249A6). Я попробую подать заявку в Apple, спасибо.   -  person KissTheCoder    schedule 18.01.2021
comment
Я столкнулся с той же проблемой и задал аналогичный вопрос, прежде чем столкнулся с вашим. Сегодня мне удалось найти обходной путь, см. мой пост stackoverflow.com/questions/66087776/   -  person Guy Brooker    schedule 08.02.2021