Discover Observation in SwiftUI

RSS for tag

Discuss the WWDC23 Session Discover Observation in SwiftUI

Posts under wwdc2023-10149 tag

19 Posts

Post

Replies

Boosts

Views

Activity

@Observable and didSet?
I'm in the process of migrating to the Observation framework but it seems like it is not compatible with didSet. I cannot find information about if this is just not supported or a new approach needs to be implemented? import Observation @Observable class MySettings { var windowSize: CGSize = .zero var isInFullscreen = false var scalingMode: ScalingMode = .scaled { didSet { ... } } ... } This code triggers this error: Instance member 'scalingMode' cannot be used on type 'MySettings'; did you mean to use a value of this type instead? Anyone knows what needs to be done? Thanks!
11
3
4.9k
Jan ’25
Binding with ForEach or List doesn't work anymore when using @Observable macro
Hi. The binding in a ForEach or List view doesn't work anymore when using the @Observable macro to create the observable object. For example, the following are the modifications I introduced to the Apple's example called "Migrating from the Observable Object Protocol to the Observable Macro" https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro struct LibraryView: View { @Environment(Library.self) private var library var body: some View { List($library.books) { $book in BookView(book: book) } } } All I did was to add the $ to turn the reference to library.books into a binding but I got the error "Cannot find '$library' in scope" Is this a bug or the procedure to use binding in lists changed? Thanks
3
0
2.4k
Oct ’24
Does code at 04:41 compile?
The code for @State doesn't seem to work. struct DonutListView: View { var donutList: DonutList @State private var donutToAdd: Donut? var body: some View { List(donutList.donuts) { DonutView(donut: $0) } Button("Add Donut") { donutToAdd = Donut() } .sheet(item: $donutToAdd) { // <-- would need a "donut in" TextField("Name", text: $donutToAdd.name) // <-- donutToAdd is optional and I'm not sure how it would be unwrapped Button("Save") { donutList.donuts.append(donutToAdd) donutToAdd = nil } Button("Cancel") { donutToAdd = nil } } } } Does anyone have a fix for this? Thanks, Dan!
1
2
1.1k
May ’24
@Observable does not conform with Equatable (and Hashable)
Since Xcode 15 beta 5, making a class with the @Observable macro no longer requires all properties to have an initialization value, as seen in the video. Just put an init that collects the properties and everything works correctly. @Observable final class Score: Identifiable { let id: Int var title: String var composer: String var year: Int var length: Int var cover: String var tracks: [String] init(id: Int, title: String, composer: String, year: Int, length: Int, cover: String, tracks: [String]) { self.id = id self.title = title self.composer = composer self.year = year self.length = length self.cover = cover self.tracks = tracks } } But there is a problem: the @Observable macro makes each property to integrate the @ObservationTracked macro that seems not to conform the types to Equatable, and in addition, to Hashable. Obviously, being a feature of each property, it is not useful to conform the class in a forced way with the static func == or with the hash(into:Hasher) function that conforms both protocols. That any class we want to be @Observable does not conform to Hashable, prevents any instance with the new pattern to be usable within a NavigationStack using the data driven navigation bindings and the navigationDestination(for:) modifier. I understand that no one has found a solution to this. If you have found it it would be great if you could share it but mainly I am making this post to invoke the mighty developers at Apple to fix this bug. Thank you very much. P.S. - I also posted a Feedback (FB12535713), but no one replies. At least that I see.
3
4
2.5k
Apr ’24
Observation and MainActor
Previously, it was recommended to use the @MainActor annotation for ObservableObject implementation. @MainActor final class MyModel: ObservableObject { let session: URLSession @Published var someText = "" init(session: URLSession) { self.session = session } } We could use this as either a @StateObject or @ObservedObject: struct MyView: View { @StateObject let model = MyModel(session: .shared) } By moving to Observation, I need to the @Observable macro, remove the @Published property wrappers and Switch @StateObject to @State: @MainActor @Observable final class MyModel { let session: URLSession var someText = "" init(session: URLSession) { self.session = session } } But switching from @StateObject to @State triggers me an error due to a call to main-actor isolated initialiser in a synchronous nonisolated context. This was not the case with @StateObject of @ObservedObject. To suppress the warning I could : mark the initializer as nonisolated but it is not actually what I want Mark the View with @MainActor but this sounds odd Both solutions does not sound nice to my eye. Did I miss something here?
9
3
7.3k
Apr ’24
@StateObject for view owning "viewModel" to use with @Observable observation framework object
I have an issue with a View that owns @Observable object (Instantize it, and is owner during the existence) in the same notion as @StateObject, however when @State is used the viewModel is re-created and deallocated on every view redraw. In the previous models, @StateObject were used when the View is owner of the object (Owner of the viewModel as example) When @Observable object is used in the same notion, @State var viewModel = ViewModel() the viewModel instance is recreated on views redraws. @StateObject was maintaining the same instance during the View existence, that however is not happening when used @Observable with @State.
2
1
2.1k
Sep ’23
NavigationSplitView crashes in Xcode, iOS Beta 7
I have a NavigationSplitView with a sidebar. When selecting a new item on the sidebar, the app crashes. The error message says: Simultaneous accesses to 0x6000030107f0, but modification requires exclusive access. Xcode shows that the crash occurs inside the generated code in my class with @Observable macro. @ObservationIgnored private let _$observationRegistrar = Observation.ObservationRegistrar() internal nonisolated func access<Member>( keyPath: KeyPath<NavModel , Member> ) { _$observationRegistrar.access(self, keyPath: keyPath) } internal nonisolated func withMutation<Member, MutationResult>( keyPath: KeyPath<NavModel , Member>, _ mutation: () throws -> MutationResult ) rethrows -> MutationResult { // Crash occurs on the following line try _$observationRegistrar.withMutation(of: self, keyPath: keyPath, mutation) } @ObservationIgnored private var _section: SidebarSection? = .one To reproduce the crash, I tap a new item on the sidebar until the app crashes. It usually only takes 1-3 times selecting a new item before the crash occurs. Below is the code for an entire app to reproduce the crash. Has anyone else encountered this issue? Thank you! import SwiftUI @main struct NavigationBugApp: App { var body: some Scene { WindowGroup { ContentView() } } } @Observable class NavModel { var section: SidebarSection? = .one } enum SidebarSection: Hashable { case one case two } struct ContentView: View { @State private var model = NavModel() var body: some View { NavigationSplitView { List(selection: $model.section) { NavigationLink("One", value: SidebarSection.one) NavigationLink("Two", value: SidebarSection.two) } .listStyle(.sidebar) } detail: { Text("Hello World") } } } #Preview { ContentView() }
2
0
1.4k
Aug ’23
can't use @Environment for Binding?
@Environment can't use for Binding? @Observable final class View1Model { var text: String = "" } struct View1: View { @State var viewModel = View1Model() var body: some View { View2() .environment(viewModel) } } struct View2: View { @Environment(View1Model.self) var viewModel var body: some View { TextField("Text", text: $viewModel.text) // Cannot find '$viewModel' in scope } }
6
2
6.2k
Aug ’23
Mix new @Observable with MVVM and Combine
We currently have our entire app written as SwiftUI Views with ViewModels (currently set as @StateObjects). SwiftUI has a new feature in iOS 17 called @Observable which simplifies the MVVM pattern and would greatly reduce the complexity of our codebase. However, our current ViewModels implement Combine pipelines on the @Published properties which allows us to do all sorts of things from validation of inputs to ensuring lists are filtered correctly. Without the @Published property wrapper in the new @Observable macro, we don't have access to those combine pipelines and so we were wondering how others have solved this? One idea we are floating around is using CurrentValueSubjects as the variable types, but that does pollute the code a little as we have to utilise .send() and .value in the Views which seems like an anti-pattern. Any thoughts or help would be greatly appreciated!
2
3
1.9k
Aug ’23
Swift compiler crash in Xcode 15 beta 3 (15A5195k)
Somehow the Swift compiler is unable to this code: @Observable class ServiceBrowser: NSObject { typealias ResolveServiceCompletionBlock = (Bool, Error?) -> Void fileprivate var resolveServiceCompletionHandler: ResolveServiceCompletionBlock? = nil } Here's the crash: 4 . While evaluating request ASTLoweringRequest(Lowering AST to SIL for file "/Users/luc/Work/Repositories/app-shared/App/Shared/Connectivity/ServiceBrowser.swift") 5 . While silgen init accessor SIL function "@$s7App14ServiceBrowserC07resolveB17CompletionHandler33_5B15C352D9CC926D1F8A0ECAC5970199LLySb_s5Error_pSgtcSgvi". for init for resolveServiceCompletionHandler (at /Users/luc/Work/Repositories/ap-shared/App/Shared/Connectivity/ServiceBrowser.swift:86:21) 6 . While emitting reabstraction thunk in SIL function "@$sSbs5Error_pSgIegyg_ytIegd_TR".
2
0
1.3k
Jul ’23
NavigationPath doesn't work with the @Observable macro iOS 17
Hello! I'm not able to push a view into a stack using new @Observable macro. import SwiftUI import Observation @Observable class NavigationModel { var path = NavigationPath() } struct ContentView: View { @State var navigationModel: NavigationModel = NavigationModel() var body: some View { NavigationStack(path: $navigationModel.path) { VStack { Button { navigationModel.path.append("Text") } label: { Text("Go to the next screen") } } .navigationDestination(for: String.self) { item in Text("Pushed view") } } } } Everything works fine when I use ObservableObject with @Published properties: class NavigationModel: ObservableObject { @Published var path = NavigationPath() } struct ContentView: View { @StateObject var navigationModel: NavigationModel = NavigationModel() var body: some View { NavigationStack(path: $navigationModel.path) { Button { navigationModel.path.append("Text") } label: { Text("Go to the next screen") } .navigationDestination(for: String.self) { item in Text("Pushed view") } } } }
1
0
1.9k
Jul ’23
@ObservationIgnored weak var - must be initialised?
I understand that @Observable currently requires all properties to be initialised. However I am surprised that opting out of observation does not work: @Observable class Assessment { var name = "" var processes: [Process] = [] } @Observable class Process { var name = "" @ObservationIgnored weak var parent: Assessment? } The error message is Return from initializer without initializing all stored properties from the Process class. Any suggestions?
0
1
1.1k
Jul ’23
Throttling and Debouncing
I want to use Throttling and Debouncing to handle the inputs from the user. These are common techniques to reduce the number of events that are triggered by the inputs. I know how to implement them with the ObservableObject protocol and Combine framework. However, I am trying to migrate to the @Observable property wrapper, which is a new feature of SwiftUI. I cannot find a way to support Throttling and Debouncing with @Observable. Does anyone have any ideas or suggestions on how to solve this problem?
1
1
1.1k
Jun ’23
didSet not longer supported in observable?
I tried to migrate some code to SwiftData and Observable...doing this I wanted to mark a ViewModel-Class with @observable but get errors when using it in combination with didSet. What's wrong with it?! @Observable struct LADVAthletes { var queryName : String = "" { didSet { guard oldValue != queryName else { return } guard queryName.count &lt; 2 else { athletesList.removeAll() return } } } var athletesList : [Athlete] = [Athlete]() } I get multiple Errors saying "Cannot find 'oldValue' in scope" "Instance member 'queryName' cannot be used on type 'LADVAthletes'; .... And so on... What's wrong with it?!
1
1
1.6k
Jun ’23
@Observable and didSet?
I'm in the process of migrating to the Observation framework but it seems like it is not compatible with didSet. I cannot find information about if this is just not supported or a new approach needs to be implemented? import Observation @Observable class MySettings { var windowSize: CGSize = .zero var isInFullscreen = false var scalingMode: ScalingMode = .scaled { didSet { ... } } ... } This code triggers this error: Instance member 'scalingMode' cannot be used on type 'MySettings'; did you mean to use a value of this type instead? Anyone knows what needs to be done? Thanks!
Replies
11
Boosts
3
Views
4.9k
Activity
Jan ’25
Binding with ForEach or List doesn't work anymore when using @Observable macro
Hi. The binding in a ForEach or List view doesn't work anymore when using the @Observable macro to create the observable object. For example, the following are the modifications I introduced to the Apple's example called "Migrating from the Observable Object Protocol to the Observable Macro" https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro struct LibraryView: View { @Environment(Library.self) private var library var body: some View { List($library.books) { $book in BookView(book: book) } } } All I did was to add the $ to turn the reference to library.books into a binding but I got the error "Cannot find '$library' in scope" Is this a bug or the procedure to use binding in lists changed? Thanks
Replies
3
Boosts
0
Views
2.4k
Activity
Oct ’24
Does code at 04:41 compile?
The code for @State doesn't seem to work. struct DonutListView: View { var donutList: DonutList @State private var donutToAdd: Donut? var body: some View { List(donutList.donuts) { DonutView(donut: $0) } Button("Add Donut") { donutToAdd = Donut() } .sheet(item: $donutToAdd) { // <-- would need a "donut in" TextField("Name", text: $donutToAdd.name) // <-- donutToAdd is optional and I'm not sure how it would be unwrapped Button("Save") { donutList.donuts.append(donutToAdd) donutToAdd = nil } Button("Cancel") { donutToAdd = nil } } } } Does anyone have a fix for this? Thanks, Dan!
Replies
1
Boosts
2
Views
1.1k
Activity
May ’24
@Observable does not conform with Equatable (and Hashable)
Since Xcode 15 beta 5, making a class with the @Observable macro no longer requires all properties to have an initialization value, as seen in the video. Just put an init that collects the properties and everything works correctly. @Observable final class Score: Identifiable { let id: Int var title: String var composer: String var year: Int var length: Int var cover: String var tracks: [String] init(id: Int, title: String, composer: String, year: Int, length: Int, cover: String, tracks: [String]) { self.id = id self.title = title self.composer = composer self.year = year self.length = length self.cover = cover self.tracks = tracks } } But there is a problem: the @Observable macro makes each property to integrate the @ObservationTracked macro that seems not to conform the types to Equatable, and in addition, to Hashable. Obviously, being a feature of each property, it is not useful to conform the class in a forced way with the static func == or with the hash(into:Hasher) function that conforms both protocols. That any class we want to be @Observable does not conform to Hashable, prevents any instance with the new pattern to be usable within a NavigationStack using the data driven navigation bindings and the navigationDestination(for:) modifier. I understand that no one has found a solution to this. If you have found it it would be great if you could share it but mainly I am making this post to invoke the mighty developers at Apple to fix this bug. Thank you very much. P.S. - I also posted a Feedback (FB12535713), but no one replies. At least that I see.
Replies
3
Boosts
4
Views
2.5k
Activity
Apr ’24
Observation and MainActor
Previously, it was recommended to use the @MainActor annotation for ObservableObject implementation. @MainActor final class MyModel: ObservableObject { let session: URLSession @Published var someText = "" init(session: URLSession) { self.session = session } } We could use this as either a @StateObject or @ObservedObject: struct MyView: View { @StateObject let model = MyModel(session: .shared) } By moving to Observation, I need to the @Observable macro, remove the @Published property wrappers and Switch @StateObject to @State: @MainActor @Observable final class MyModel { let session: URLSession var someText = "" init(session: URLSession) { self.session = session } } But switching from @StateObject to @State triggers me an error due to a call to main-actor isolated initialiser in a synchronous nonisolated context. This was not the case with @StateObject of @ObservedObject. To suppress the warning I could : mark the initializer as nonisolated but it is not actually what I want Mark the View with @MainActor but this sounds odd Both solutions does not sound nice to my eye. Did I miss something here?
Replies
9
Boosts
3
Views
7.3k
Activity
Apr ’24
@StateObject for view owning "viewModel" to use with @Observable observation framework object
I have an issue with a View that owns @Observable object (Instantize it, and is owner during the existence) in the same notion as @StateObject, however when @State is used the viewModel is re-created and deallocated on every view redraw. In the previous models, @StateObject were used when the View is owner of the object (Owner of the viewModel as example) When @Observable object is used in the same notion, @State var viewModel = ViewModel() the viewModel instance is recreated on views redraws. @StateObject was maintaining the same instance during the View existence, that however is not happening when used @Observable with @State.
Replies
2
Boosts
1
Views
2.1k
Activity
Sep ’23
NavigationSplitView crashes in Xcode, iOS Beta 7
I have a NavigationSplitView with a sidebar. When selecting a new item on the sidebar, the app crashes. The error message says: Simultaneous accesses to 0x6000030107f0, but modification requires exclusive access. Xcode shows that the crash occurs inside the generated code in my class with @Observable macro. @ObservationIgnored private let _$observationRegistrar = Observation.ObservationRegistrar() internal nonisolated func access<Member>( keyPath: KeyPath<NavModel , Member> ) { _$observationRegistrar.access(self, keyPath: keyPath) } internal nonisolated func withMutation<Member, MutationResult>( keyPath: KeyPath<NavModel , Member>, _ mutation: () throws -> MutationResult ) rethrows -> MutationResult { // Crash occurs on the following line try _$observationRegistrar.withMutation(of: self, keyPath: keyPath, mutation) } @ObservationIgnored private var _section: SidebarSection? = .one To reproduce the crash, I tap a new item on the sidebar until the app crashes. It usually only takes 1-3 times selecting a new item before the crash occurs. Below is the code for an entire app to reproduce the crash. Has anyone else encountered this issue? Thank you! import SwiftUI @main struct NavigationBugApp: App { var body: some Scene { WindowGroup { ContentView() } } } @Observable class NavModel { var section: SidebarSection? = .one } enum SidebarSection: Hashable { case one case two } struct ContentView: View { @State private var model = NavModel() var body: some View { NavigationSplitView { List(selection: $model.section) { NavigationLink("One", value: SidebarSection.one) NavigationLink("Two", value: SidebarSection.two) } .listStyle(.sidebar) } detail: { Text("Hello World") } } } #Preview { ContentView() }
Replies
2
Boosts
0
Views
1.4k
Activity
Aug ’23
can't use @Environment for Binding?
@Environment can't use for Binding? @Observable final class View1Model { var text: String = "" } struct View1: View { @State var viewModel = View1Model() var body: some View { View2() .environment(viewModel) } } struct View2: View { @Environment(View1Model.self) var viewModel var body: some View { TextField("Text", text: $viewModel.text) // Cannot find '$viewModel' in scope } }
Replies
6
Boosts
2
Views
6.2k
Activity
Aug ’23
How to Debounce and Throttle Using @Observable
I want to transition from Combine to the Observation framework my question is how do I Debounce user input with the Observation framework there appears now way to do this. Any and all help is welcomed.
Replies
4
Boosts
2
Views
3k
Activity
Aug ’23
Mix new @Observable with MVVM and Combine
We currently have our entire app written as SwiftUI Views with ViewModels (currently set as @StateObjects). SwiftUI has a new feature in iOS 17 called @Observable which simplifies the MVVM pattern and would greatly reduce the complexity of our codebase. However, our current ViewModels implement Combine pipelines on the @Published properties which allows us to do all sorts of things from validation of inputs to ensuring lists are filtered correctly. Without the @Published property wrapper in the new @Observable macro, we don't have access to those combine pipelines and so we were wondering how others have solved this? One idea we are floating around is using CurrentValueSubjects as the variable types, but that does pollute the code a little as we have to utilise .send() and .value in the Views which seems like an anti-pattern. Any thoughts or help would be greatly appreciated!
Replies
2
Boosts
3
Views
1.9k
Activity
Aug ’23
KeyboardType(.NumericPad) not supporting For WatchOS in SwiftUI
TextField("BG Value", text: $text).keyboardType(.numberPad) when ever i tried to show numberpad as TextField Input i am getting error Error as below : Cannot infer contextual base in reference to member 'numberPad' Value of type 'TextField' has no member 'keyboardType' Any suggest me on this issue
Replies
1
Boosts
0
Views
1.6k
Activity
Jul ’23
Swift compiler crash in Xcode 15 beta 3 (15A5195k)
Somehow the Swift compiler is unable to this code: @Observable class ServiceBrowser: NSObject { typealias ResolveServiceCompletionBlock = (Bool, Error?) -> Void fileprivate var resolveServiceCompletionHandler: ResolveServiceCompletionBlock? = nil } Here's the crash: 4 . While evaluating request ASTLoweringRequest(Lowering AST to SIL for file "/Users/luc/Work/Repositories/app-shared/App/Shared/Connectivity/ServiceBrowser.swift") 5 . While silgen init accessor SIL function "@$s7App14ServiceBrowserC07resolveB17CompletionHandler33_5B15C352D9CC926D1F8A0ECAC5970199LLySb_s5Error_pSgtcSgvi". for init for resolveServiceCompletionHandler (at /Users/luc/Work/Repositories/ap-shared/App/Shared/Connectivity/ServiceBrowser.swift:86:21) 6 . While emitting reabstraction thunk in SIL function "@$sSbs5Error_pSgIegyg_ytIegd_TR".
Replies
2
Boosts
0
Views
1.3k
Activity
Jul ’23
NavigationPath doesn't work with the @Observable macro iOS 17
Hello! I'm not able to push a view into a stack using new @Observable macro. import SwiftUI import Observation @Observable class NavigationModel { var path = NavigationPath() } struct ContentView: View { @State var navigationModel: NavigationModel = NavigationModel() var body: some View { NavigationStack(path: $navigationModel.path) { VStack { Button { navigationModel.path.append("Text") } label: { Text("Go to the next screen") } } .navigationDestination(for: String.self) { item in Text("Pushed view") } } } } Everything works fine when I use ObservableObject with @Published properties: class NavigationModel: ObservableObject { @Published var path = NavigationPath() } struct ContentView: View { @StateObject var navigationModel: NavigationModel = NavigationModel() var body: some View { NavigationStack(path: $navigationModel.path) { Button { navigationModel.path.append("Text") } label: { Text("Go to the next screen") } .navigationDestination(for: String.self) { item in Text("Pushed view") } } } }
Replies
1
Boosts
0
Views
1.9k
Activity
Jul ’23
@ObservationIgnored weak var - must be initialised?
I understand that @Observable currently requires all properties to be initialised. However I am surprised that opting out of observation does not work: @Observable class Assessment { var name = "" var processes: [Process] = [] } @Observable class Process { var name = "" @ObservationIgnored weak var parent: Assessment? } The error message is Return from initializer without initializing all stored properties from the Process class. Any suggestions?
Replies
0
Boosts
1
Views
1.1k
Activity
Jul ’23
Throttling and Debouncing
I want to use Throttling and Debouncing to handle the inputs from the user. These are common techniques to reduce the number of events that are triggered by the inputs. I know how to implement them with the ObservableObject protocol and Combine framework. However, I am trying to migrate to the @Observable property wrapper, which is a new feature of SwiftUI. I cannot find a way to support Throttling and Debouncing with @Observable. Does anyone have any ideas or suggestions on how to solve this problem?
Replies
1
Boosts
1
Views
1.1k
Activity
Jun ’23
Why does @Observable need an initial value?
Why would it not allow to set the value in the init statement. The @Model allows this and as I understand it also acts as an @Observable.
Replies
2
Boosts
0
Views
1.8k
Activity
Jun ’23
How does one specify a minimum target of iOS(.v17) in a swift package
Looking for something like this. let package = Package( name: "Core", defaultLocalization: "en", platforms: [ .iOS(.v16) ], Also, I assume since my package is still using v16, I will not see new types like @Observable. Is that a valid assumption as to why I don't see these new types?
Replies
3
Boosts
0
Views
3.9k
Activity
Jun ’23
didSet not longer supported in observable?
I tried to migrate some code to SwiftData and Observable...doing this I wanted to mark a ViewModel-Class with @observable but get errors when using it in combination with didSet. What's wrong with it?! @Observable struct LADVAthletes { var queryName : String = "" { didSet { guard oldValue != queryName else { return } guard queryName.count &lt; 2 else { athletesList.removeAll() return } } } var athletesList : [Athlete] = [Athlete]() } I get multiple Errors saying "Cannot find 'oldValue' in scope" "Instance member 'queryName' cannot be used on type 'LADVAthletes'; .... And so on... What's wrong with it?!
Replies
1
Boosts
1
Views
1.6k
Activity
Jun ’23
"Discover Observation in SwiftUI" session has a bug
They provide an example on using @Observable in minute 5:14 : @Observable class Account { var userName: String? } However, if you put that in Xcode this gives an error: @Observable requires property 'userName' to have an initial value (from macro 'Observable') Anyone else seeing this?
Replies
3
Boosts
1
Views
1.4k
Activity
Jun ’23