Post

Replies

Boosts

Views

Activity

Why does this fix my Navigation in iOS 16.4?
I've been trying to figure out why my navigation is broken in iOS 16.4 It worked in 16.3. I have been able to fix the problem, however, I would like to know why this fixes it. I don't understand. The problem I was trying to fix is this: Whenever I appended an item to the NavigationPath, the new view never got pushed (it did in iOS 16 - 16.3). Nothing happened in the view. Then, when I tap on a normal navigation link as in NavigationLink(value: Destinations.goal), the previously appended path would push, followed by a push of the view specified for the NavigationLink's value in .navigationDestination(for:). In MainGoalView, the line navItem.navigationPath.append(Destinations.formStatus) had no effect when I tap on "Submitted Forms". However, if I tapped "Submitted Forms", then tap on "Information", both links get executed so that I see the view "Information". Then tapping the Back button, I see "Form Status". (I also saw "Form Status" momentarily before "Information" was pushed.) struct MainGoalView: View { @EnvironmentObject var navItem: AppNavigationItem enum Destinations: Hashable, Codable { case formStatus, information } @State private var isShowingAlert = false @State private var isShowingForms = false @State private var navigationPath = NavigationPath() var body: some View { List { Section { UpcomingGoalsView() } header: { Text("Upcoming") } Section { Text("Form Summary") } header: { SectionActionHeader(title: "Submitted Forms", actionText: "View") { navItem.navigationPath.append(Destinations.formStatus) // <- HERE } } Section { NavigationLink(value: Destinations.information) { Text("Information") } } header: { Text("Information") } } .listStyle(.insetGrouped) .navigationDestination(for: Destinations.self) { value in switch value { case .formStatus: Text("Form Status") case .information: Text("Information") } } } } I finally tracked the problem down to the code that sets up my tab bar. Before looking at that code, here is the code code that configures the tab bar. The AppNavigator class contains a list of AppNavigationItems that defines each tab of the tab bar. (This was set up so it could be used for a tab bar, or for another interface such as a NavigationSplitView) enum AppNavigatorType { case insights case people } class AppNavigator: ObservableObject { static let shared = AppNavigator() static let defaultStartTab = AppNavigatorType.insights @Published var selectedNavigatorType: AppNavigatorType? = AppNavigator.defaultStartTab var items: [AppNavigationItem] = [ AppNavigationItem(AnyView(InsightsView()), type: .insights, title: "Insights", systemImageName: "chart.bar"), AppNavigationItem(AnyView(Text("Not Implemented")), type: .people, title: "People", systemImageName: "person"), ] } class AppNavigationItem: ObservableObject, Identifiable { @Published var navigationPath = NavigationPath() var id: String { title } var view: AnyView var type: AppNavigatorType? var title: String private var systemImageName: String var image: Image init(_ view: AnyView, type: AppNavigatorType, title: String, systemImageName: String) { self.view = view self.type = type self.title = title self.systemImageName = systemImageName self.image = Image(systemName: systemImageName) } } Finally, here is the code where I was able to correct the problem, but I'm not sure why it fixes it. First, here is the version that doesn't work correctly. I was never quite sure as to why I had to use the $ to get it to compile, but it all worked in iOS 16 - 16.3 public struct MainTabView: View { @EnvironmentObject var navigator: AppNavigator public var body: some View { TabView { ForEach ($navigator.items) { $navItem in // <- Why the $ NavigationStack(path: $navItem.navigationPath) { let _: Int = { print(navItem.navigationPath); return 0 }() navItem.view } .environmentObject(navItem) .tabItem { Text(navItem.title) navItem.image .environment(\.symbolVariants, navigator.selectedNavigatorType == navItem.type ? .fill : .none) } .tag(navItem.type) .navigationTitle(navItem.title) .id(navItem.id) } } } } Unfortunately, it doesn't work in iOS 16.4, as already described. I changed the above code for MainTableView to the following, and now it works in iOS 16.4. I just moved the code inside the ForEach into another View. I would love someone smarter than me to help me understand why. public struct MainTabView: View { @EnvironmentObject var navigator: AppNavigator public var body: some View { TabView { ForEach (navigator.items) { navItem in // <- Ah! $ not needed now. TabBarRootView(navItem: navItem) } } } } struct TabBarRootView: View { @EnvironmentObject private var navigator: AppNavigator @ObservedObject var navItem: AppNavigationItem // <- navItem is an ObservableObject, and this is observing it. var body: some View { NavigationStack(path: $navItem.navigationPath) { // <- Pass the binding to the published navigationPath. let _: Int = { print(navItem.navigationPath); return 0 }() navItem.view } .environmentObject(navItem) .tabItem { Text(navItem.title) navItem.image .environment(\.symbolVariants, navigator.selectedNavigatorType == navItem.type ? .fill : .none) } .tag(navItem.type) .navigationTitle(navItem.title) .id(navItem.id) } }
2
0
837
Mar ’23
SwiftUI Preview quit working: use of undeclared type in thunk
My preview was working great. Then, without any code modifications, I went to show it to my colleagues and it started failing when I hit resume (I made no modifications to this project. I did work on other projects in Xcode in the meantime). Now I cannot make it work.I've cleaned (Product | Clean Build Folder), and deleted ~/Library/Developer/Xcode/DerivedData.When I hit Resume in the preview canvas, the top line of the canvas shows "Failed to build ViewControllerPreviews"Clicking the Diagnostics button shows:use of undeclared type 'ViewControllerPreviews'----------------------------------------.../Library/Developer/Xcode/DerivedData/ACUIKit-gjaonztkyzvcudalxmalekjsfacd/Build/Intermediates.noindex/Previews/ACUIKitApp/Intermediates.noindex/ACUIKit.build/Debug-iphonesimulator/ACUIKit.build/Objects-normal/x86_64/ViewControllerPreviews.2.preview-thunk.swift:11:11: error: use of undeclared type 'ViewControllerPreviews'extension ViewControllerPreviews { ^~~~~~~~~~~~~~~~~~~~~~ViewControllerPreviews is in the ACUIKitApp target. It is not the ACUIKit framework target.ViewControllerPreviews is previewing UIViewControllers that are defined in the app (not the framework).Inspecting the file referred to above, I see@_private(sourceFile: "ViewControllerPreviews.swift")import ACUIKit #if DEBUG import ACUIKit #endif #if DEBUG import SwiftUI #endif import SwiftUI #if DEBUG extension ViewControllerPreviews { @_dynamicReplacement(for: updateUIViewController(_:context:)) private func __preview__updateUIViewController(_ uiView: ViewControllerPreviews.UIViewControllerType, context: UIViewControllerRepresentableContext) { #sourceLocation(file: "/Users/jthomas/Dev/iOS-ACUIKit/ACUIKitApp/ViewControllerPreviews.swift", line: 94) #sourceLocation() } } #endif . . .There is a similar error message for every reference to ViewControllerPreviews in the file.I've reduced my preview code to the following, and get the same error.#if DEBUG import SwiftUI import ACUIKit struct ViewControllerPreviews: PreviewProvider { static var previews: some View { ViewControllerPreviews() } } extension ViewControllerPreviews: UIViewControllerRepresentable { typealias UIViewControllerType = DynamicFontsTableViewController func makeUIViewController(context: UIViewControllerRepresentableContext&lt;ViewControllerPreviews&gt;) -&gt; DynamicFontsTableViewController { DynamicFontsTableViewController(core: Core(state: AppState(theme: Theme.trees))) } func updateUIViewController(_ uiViewController: DynamicFontsTableViewController, context: UIViewControllerRepresentableContext&lt;ViewControllerPreviews&gt;) { } } #endifThis happened to me before. Just deleting the file, then adding it back wasn't enough to fix the problem. The way I finally fixed it was to remove my project (delete project directory and re-clone from git), then add all the preview code back in again. I want to use previews, but I can't if they just quit working. My work-around is too much.Xcode 11.3.1Any idea what I can do to get this working again?
0
0
1.4k
Jan ’20