Post

Replies

Boosts

Views

Activity

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") } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
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() } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
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
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Nov ’23
Reply to When using keyboardShortcut, instance of StateObject is not deinitialized
Upon further investigation, I believe there's a high possibility that this is a bug. In the code below, model2 is not referenced by Button.action, yet deinit is not called for model2 just like for model. struct ContentView: View { @StateObject var model = Model() @StateObject var model2 = Model2() var body: some View { VStack { Button("Toggle") { model.flag.toggle() } .keyboardShortcut(.space, modifiers: []) } .padding() } } @MainActor class Model: ObservableObject{ @Published var flag: Bool = false init() { print("Model.init") } deinit { print("Model.deinit") } } @MainActor class Model2: ObservableObject{ @Published var flag: Bool = false init() { print("Model2.init") } deinit { print("Model2.deinit") } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Oct ’23
Reply to Infinite Loop Issue with View's onAppear and onDisappear in iOS 17 Beta
In my app, the above workaround caused another problem. But, I could avoid it by changing the next code using DispatchQueue.main.async. I hope this issue will be resolved by the public release of iOS 17. struct SampleSection: View { @State private var isLoaded = false var body: some View { let _ = Self._printChanges() Group { if !isLoaded { Section("Header") {} .hidden() } else { Section("Header") { Text("Text") } } } .onAppear { DispatchQueue.main.async { // or Task { @MainActor in NSLog("SampleSection onAppear.") isLoaded = true } } .onDisappear() { DispatchQueue.main.async { // or Task { @MainActor in NSLog("Sample Section onDisappear.") isLoaded = false } } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jul ’23
Reply to Infinite Loop Issue with View's onAppear and onDisappear in iOS 17 Beta
Here is a workaround for this issue in the reproduction code. struct SampleSection: View { @State private var isLoaded = false var body: some View { let _ = Self._printChanges() if !isLoaded { Section("Header") {} .hidden() .onAppear { NSLog("SampleSection onAppear.") isLoaded = true } } else { Section("Header") { Text("Text") } .onDisappear() { NSLog("Sample Section onDisappear.") isLoaded = false } } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jul ’23
Reply to iOS 16.4 NavigationStack Behavior Unstable
After modifying the ContentView as shown below, the transition to the SubView now works. (🌟 indicates the modified parts) However, since the cause of the issue is unknown, I cannot judge whether this is an appropriate workaround or not. struct ContentView: View { @StateObject private var model = ContentModel() @State private var selectedData: Value? // 🌟 @State private var isShowingSubView = false @Environment(\.dismiss) private var dismiss init() { } var body: some View { List(selection: $selectedData) { ForEach(model.vals) { val in NavigationLink(value: val) { Text("\(val.num)") } } } // 🌟 .onChange(of: selectedData, perform: { newValue in // In production code, convert data here. isShowingSubView = newValue != nil }) .navigationDestination(isPresented: $isShowingSubView, destination: { SubView(kind: model.kind) // SubView() }) .onChange(of: isShowingSubView) { newValue in if !newValue && selectedData != nil { selectedData = nil } } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Apr ’23