Background
Hi, I've been working with MacCatalyst to build a universal app, however I've run into a problem (perhaps a bug?) with SwiftUI's List component. I think I'm implementing the list correctly as I've looked at Apple's and Paul Hudson's examples and a few others to make sure I was implementing the list correctly. This only occurs when building a target for MacCatalyst. The code works fine on iPhones (real devices and simulators).
Problem
I make a parent list inside of a NavigationView, call it “List A”, which acts as a sidebar in MacCatalyst.
Each item in List A is a NavigationLink. One of these NavigationLink’s destination view is a view containing another list (List B). When navigating to list B, it typically freeze up after an initial scroll or two. After it freezes, the only way to unfreeze it is to either pop out of the view and push back in, sometimes resize the window, or add/remove something from the list.
Minimal Reproducible Example
The steps below are for a minimal reproducible example:
New Xcode project using the UIKit LifeCycle and SwiftUI Interface
Tick the MacCatalyst option
Add scene delegate code
Add all other code into one file
Notes
• Sometimes its scrolls fine for a little bit, but eventually it always freezes.
• The CPU is 0% after freeze but then goes to a typical %15 percent when trying to scroll while frozen.
• The list is the only piece of UI that freezes, everything else is functional.
Scene Delegate Code
All Other Code
Hi, I've been working with MacCatalyst to build a universal app, however I've run into a problem (perhaps a bug?) with SwiftUI's List component. I think I'm implementing the list correctly as I've looked at Apple's and Paul Hudson's examples and a few others to make sure I was implementing the list correctly. This only occurs when building a target for MacCatalyst. The code works fine on iPhones (real devices and simulators).
Problem
I make a parent list inside of a NavigationView, call it “List A”, which acts as a sidebar in MacCatalyst.
Each item in List A is a NavigationLink. One of these NavigationLink’s destination view is a view containing another list (List B). When navigating to list B, it typically freeze up after an initial scroll or two. After it freezes, the only way to unfreeze it is to either pop out of the view and push back in, sometimes resize the window, or add/remove something from the list.
Minimal Reproducible Example
The steps below are for a minimal reproducible example:
New Xcode project using the UIKit LifeCycle and SwiftUI Interface
Tick the MacCatalyst option
Add scene delegate code
Add all other code into one file
Notes
• Sometimes its scrolls fine for a little bit, but eventually it always freezes.
• The CPU is 0% after freeze but then goes to a typical %15 percent when trying to scroll while frozen.
• The list is the only piece of UI that freezes, everything else is functional.
Scene Delegate Code
Code Block 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() } }
All Other Code
Code Block 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) ) } } } .navigationViewStyle(StackNavigationViewStyle()) .navigationBarTitle("Roles") } @ViewBuilder func viewForRole(role: ViewModel.Role) -> some View { if role == .admin { QueryView(vm: QueryView.ViewModel()) }else if role == .moderator { Text("Coming soon!") }else{ Text(role.rawValue) } } } extension RootView { class ViewModel:ObservableObject { @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(0..<vm.models.count, id: \.self) { i in Text(vm.models[i]) } } Button("Add Model") { vm.addModel() } .padding() } } } 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)") } } }