Post

Replies

Boosts

Views

Activity

Reply to iOS18 beta2: NavigationStack, Views Being Popped Automatically
This issue still occurs in iOS 18.0 (22A5316j), Xcode 16.0 beta4(16A5211f). I have confirmed that the problem persists even when using @Observable with Observation. The result changes only depending on whether @Environment is defined in the lower-level View. When tapping through the cells to display the DetailView, the screen automatically pops back to the WordBookView. If I comment out @Environment(Env.self) in the WordBookView, the automatic pop does not occur. This issue occurs only on iOS 18.0 beta. It does not occur in iOS 17.5 or earlier. import SwiftUI import Observation @Observable class Env { } struct Book: Identifiable, Sendable, Hashable { let id: UUID = UUID() let name: String var words: [Word] = [] init(name: String) { self.name = name } } struct Word: Identifiable, Sendable, Hashable { let id: UUID = UUID() var word: String init(word: String) { self.word = word } } let staticBooks: [Book] = { (1...10).enumerated().map { var b = Book(name: "Book-\($0)") b.words = (1...100).enumerated().map { return Word(word: "\(b.name)-Word-\($0)") } return b } }() @main struct iOS18NavigaationStackSampleApp: App { var body: some Scene { WindowGroup { NavigationStack() { ContentView() } } } } struct ContentView: View { @State private var env = Env() var body: some View { WordListView() .environment(env) } } struct WordListView: View { @Environment(Env.self) private var env @State var books:[Book] = staticBooks @State var selected: Book? var body: some View { List(selection: $selected) { ForEach(books) { book in NavigationLink(value: book) { Text(book.name) } } } .navigationDestination(item: $selected) { book in WordBookView(book: book) .environment(env) } } } struct WordBookView: View { @Environment(Env.self) var env let book: Book @State var selected: Word? var body: some View { List(selection: $selected) { ForEach(book.words) { word in NavigationLink(value: word) { Text(word.word) } } } .navigationDestination(item: $selected) { word in DetailView(word: word) } } } struct DetailView: View { let word: Word var body: some View { Text(word.word) } }
Aug ’24
Reply to iOS18 beta2 NavigationStack: Tapping Back from a lower-level View returns to the Root View / No transition animation
Thank you for the detailed explanation. I have a question. This example shows undefined behavior. How can SwiftUI developers know that this behavior is undefined? I couldn't find it in the NavigationLink documentation. And thank you for the code rewrite. The sample code worked as expected. In our production code, I will avoid mixing value-destination and view-destination and will use value-destination exclusively. I also understood that using get-set binding for navigationDestination(isPresented:) can cause animation issues. To add, I am using this method to support iOS versions prior to iOS16, where navigationDestination(item:destination) is not available, and it works for versions before iOS18. However, after slightly modifying the rewritten code to match our production code, I encountered a pop issue again. Specifically, when I changed .navigationDestination(for:) to .navigationDestination(item:) within RootView, it automatically pops during the first transition from ContentView to SubView. This issue occurs when using value-destination. In any case, the issue in this article has been resolved, so I will continue the discussion in the other post: iOS18 beta2: NavigationStack, Views Being Popped Automatically.
Jul ’24
Reply to iOS18 beta2: NavigationStack, Views Being Popped Automatically
Thank you for the explanation at [https://developer.apple.com/forums/thread/758371]. As you understand, I am using navigationDestination(isPresented ) with get/set binding because navigationDestination(item:) is only supported from iOS 17 onwards. Our product code supports iOS 16 and later. (The product itself also supports iOS 15, so we are using NavigationView as well.) Additionally, when I modified the code provided in the post to be closer to our product code by changing navigationDestination(for:) to navigationDestination(item:), the pop issue reoccurred (during the transition from contentView to subView). Therefore, I believe this issue is not related to the view-destination or value-destination problem. As a workaround, I have confirmed that commenting out @Environment(.dismiss) defined in ContentView avoids the issue. While the code in this article is very simple, our product code is enormous and has a very complex structure, making it extremely difficult to pinpoint the cause when behavior changes with or without @Environment. The following code is automatically popped when navigating from ContentView to SubView on iOS 18 beta 2, but this does not happen on iOS 17.5. import SwiftUI struct Selection: Hashable, Identifiable { var num: Int var id: Int { num } } enum Kind: Hashable { case a case b } struct RootView3: View { @State var kind: Kind? = nil @State var vals: [Selection] = (1...5).map(Selection.init(num:)) @State var selection: Selection? var body: some View { if #available(iOS 17.0, *) { NavigationStack { List(selection: $kind) { NavigationLink("Album-a", value: Kind.a) NavigationLink("Album-b", value: Kind.b) } .navigationDestination(item: $kind, destination: { kind in ContentView3(vals: $vals, selection: $selection) }) // .navigationDestination(for: Kind.self) { kind in // ContentView3(vals: $vals, selection: $selection) // } } } } } @available(iOS 17.0, *) struct ContentView3: View { @Binding var vals: [Selection] @Binding var selection: Selection? @Environment(\.dismiss) private var dismiss var body: some View { List(selection: $selection) { ForEach(self.vals) { val in NavigationLink(value: val) { Text("\(String(describing: val))") } } } .navigationDestination(item: $selection) { sel in SubView3(kind: .a, selection: sel) } } } struct SubView3: View { let kind: Kind let selection: Selection var body: some View { Text("Content. \(kind): \(selection)") } }
Jul ’24
Reply to iOS18 beta2: NavigationStack, Views Being Popped Automatically
Thank you for your response. I tried the suggested solution, and although it resolved the issue of the view being popped automatically, a different problem has now arisen. (The new issue: Tapping Back from a lower-level View returns to the Root View / No transition animation ) However, while this fix may work for the simplest code, I think it cannot be applied to our production code for the following three reasons: This fix requires placing navigationDestination directly under NavigationStack. In our production code, we have multiple levels such as two, three, or more, each handling different data models within a large navigation view. It's not practical to describe all levels of navigationDestination directly under NavigationStack. This fix introduces another problem, making it unsuitable for inclusion in our production code at this time. I am unsure whether this behavior is due to a specification change in iOS 18 or a bug in the iOS 18 beta, and whether this solution is just a temporary workaround. Regardless, thank you for your advice. I hope the behavior of NavigationStack and SwiftUI stabilizes soon.
Jun ’24
Reply to iOS18 beta2: NavigationStack, Views Being Popped Automatically
Out of curiosity, have you tried using the Observable macro instead of the older ObservableObject? Thank you for your response. Using Observation, this issue no longer occurs. Since this problem does not occur in iOS 17.x, it seems to be an issue with iOS 18.0 beta 2. Additionally, as our product code needs to support iOS 15 and later, replacing Observation—which is only available from iOS 17—with Model and View code would lead to considerable duplication and make it difficult. I also want to share that I was able to reproduce the issue with the following code, which does not use ObservableObject or Observation. import SwiftUI enum Kind { case none, a, b, c } // Selection is storing the selected values in the NavigationStack. struct Selection: Hashable, Identifiable { let id = UUID() let num: Int init(num: Int) { self.num = num print("id: \(id), num: \(num)") } } // Data is corresponding to the selection. struct Data { let data: Int } @main struct iOS16_4NavigationSampleApp: App { var body: some Scene { WindowGroup { RootView() } } } struct RootView: View { var body: some View { if #available(iOS 16.0, *) { NavigationStack { NavigationLink { ContentView() } label: { Text("album") } } } else { EmptyView() } } } struct ContentView: View { @State var kind: Kind = .a @State var vals: [Selection] = { return (1...5).map { Selection(num: $0) } }() @State var selection: Selection? @Environment(\.dismiss) private var dismiss var body: some View { list .onChange(of: self.selection) { newValue in print("changed: \(String(describing: newValue?.num))") } } @ViewBuilder private var list: some View { if #available(iOS 16.0, *) { List(selection: $selection) { ForEach(self.vals) { val in NavigationLink(value: val) { Text("\(String(describing: val))") } } } .navigationDestination(isPresented: .init(get: { return selection != nil }, set: { newValue in if !newValue { selection = nil } }), destination: { SubView(kind: .a) }) } } } // struct SubView: View { init(kind: Kind) { } init() { } var body: some View { Text("Content") } }
Jun ’24
Reply to Are changes to published embedded objects really not detected in SwiftUI?
How about trying this? @MainActor class UserManager: ObservableObject { @Published var user: User private var cancelSet: Set<AnyCancellable> = .init() init() { self.user = User() self.user.objectWillChange.sink { [weak self] in self?.objectWillChange.send() } .store(in: &cancelSet) Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in Task { @MainActor in self.user.ID += "1" } } } } struct ContentView: View { @ObservedObject var userManager: UserManager var body: some View { VStack { Text("\(userManager.user.ID)") } .padding() } }
Jan ’24
Reply to App Freezes with AVPlayer Inside NavigationStack on iOS 17.2 beta
Update: I have tested on both the iPad Simulator and an actual iPad device. iPad Simulator (iPadOS 17.2 (21C5029e)): The issue occurs iPad real device (iPadOS 17.2 (21C5029g)): The issue does not occur I haven't been able to confirm on an actual iPhone, but it might be an issue that occurs only on the Simulator. It may be related to the thread below. Simulator crashing with iOS < 14. Started happening since Big Sur https://developer.apple.com/forums/thread/667921?page=2
Nov ’23