admin管理员组文章数量:1182775
I am not entire sure why using the @Observable tag does not work the same as using the 'old' way which is using @Published and ObservableObject and @StateObject. I am just curious why that wouldn't work since using @Observable is supposed to be the new way.
Also I am new to SwiftUI.
I am trying to get the Picker from the view screen to update the variable currentSelection
from SettingsViewModel on any user interactions with the picker.
import Foundation
@Observable
class SettingsViewModel {
var currentSelection : ColorOptionEnum
var dataHandler : DataHandler
init() {
let localdataHandler: DataHandler = .init()
currentSelection = localdataHandler.currentBibleVersion
dataHandler = localdataHandler
}
}
-------------
import SwiftUI
struct SettingsView: View {
var settingsViewModel : SettingsViewModel = .init()
var body: some View {
Form {
Text("Mode")
Picker(
"Mode",
selection: $settingsViewModel.currentSelection // GETTING Error here ( cannot find '$settingsViewModel' in scope)
) {
Text(
"Green"
)
.tag(
ColorOptionEnum.Green
)
Text(
"Blue"
)
.tag(
ColorOptionEnum.Blue )
}
}
}
}
#Preview {
SettingsView()
}
This version works
import Foundation
class SettingsViewModel: ObservableObject {
@Published var currentSelection : ColorOptionEnum
var dataHandler : DataHandler
init() {
let localdataHandler: DataHandler = .init()
currentSelection = localdataHandler.currentBibleVersion
dataHandler = localdataHandler
}
}
-------------
import SwiftUI
struct SettingsView: View {
@StateObject var settingsViewModel : SettingsViewModel = .init()
var body: some View {
Form {
Text("Mode")
Picker(
"Mode",
selection: $settingsViewModel.currentSelection // No error
) {
Text(
"Green"
)
.tag(
ColorOptionEnum.Green
)
Text(
"Blue"
)
.tag(
ColorOptionEnum.Blue
)
}
}
}
}
#Preview {
SettingsView()
}
I am not entire sure why using the @Observable tag does not work the same as using the 'old' way which is using @Published and ObservableObject and @StateObject. I am just curious why that wouldn't work since using @Observable is supposed to be the new way.
Also I am new to SwiftUI.
I am trying to get the Picker from the view screen to update the variable currentSelection
from SettingsViewModel on any user interactions with the picker.
import Foundation
@Observable
class SettingsViewModel {
var currentSelection : ColorOptionEnum
var dataHandler : DataHandler
init() {
let localdataHandler: DataHandler = .init()
currentSelection = localdataHandler.currentBibleVersion
dataHandler = localdataHandler
}
}
-------------
import SwiftUI
struct SettingsView: View {
var settingsViewModel : SettingsViewModel = .init()
var body: some View {
Form {
Text("Mode")
Picker(
"Mode",
selection: $settingsViewModel.currentSelection // GETTING Error here ( cannot find '$settingsViewModel' in scope)
) {
Text(
"Green"
)
.tag(
ColorOptionEnum.Green
)
Text(
"Blue"
)
.tag(
ColorOptionEnum.Blue )
}
}
}
}
#Preview {
SettingsView()
}
This version works
import Foundation
class SettingsViewModel: ObservableObject {
@Published var currentSelection : ColorOptionEnum
var dataHandler : DataHandler
init() {
let localdataHandler: DataHandler = .init()
currentSelection = localdataHandler.currentBibleVersion
dataHandler = localdataHandler
}
}
-------------
import SwiftUI
struct SettingsView: View {
@StateObject var settingsViewModel : SettingsViewModel = .init()
var body: some View {
Form {
Text("Mode")
Picker(
"Mode",
selection: $settingsViewModel.currentSelection // No error
) {
Text(
"Green"
)
.tag(
ColorOptionEnum.Green
)
Text(
"Blue"
)
.tag(
ColorOptionEnum.Blue
)
}
}
}
}
#Preview {
SettingsView()
}
Share
Improve this question
edited Jan 26 at 22:34
HangarRash
15k5 gold badges19 silver badges55 bronze badges
asked Jan 26 at 19:20
AnsilansAnsilans
31 bronze badge
New contributor
Ansilans is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
9
|
Show 4 more comments
1 Answer
Reset to default 0The error cannot find '$settingsViewModel' in scope
is because Picker
requires a binding for its selection parameter. When you use a var settingsViewModel : SettingsViewModel = .init()
, you don't get a binding to your model.
While @State
does get you a binding, it should only be used if it's considered to be the owner of the object. Otherwise, if the owner is a parent view, you can accept it as a Binding
in your child view or when using @Observable
, you can accept it as an object and get a binding to it in your child view, using @Bindable
.
Note: Since your code wasn't reproducible due to lacking the DataHandler
class and the ColorOptionEnum
, I commented it out in the example code below and added a sample enum to make it work:
import Foundation
import SwiftUI
enum ColorOptionEnum {
case green, blue, orange // <- cases should be lowercased
var color: Color {
switch self {
case .green: return .green
case .blue: return .blue
case .orange: return .orange
}
}
}
@Observable
class DemoSettings {
var currentSelection : ColorOptionEnum = .green
// var dataHandler : DataHandler
// init() {
// let localdataHandler: DataHandler = .init()
// currentSelection = localdataHandler.currentBibleVersion
// dataHandler = localdataHandler
// }
}
//Parent view
struct DemoSettingsRootView: View {
//State value
@State private var demoSettings = DemoSettings() // <- Parent view owns the settings object
//Body
var body: some View {
DemoSettingsView(settings: demoSettings) // <- Settings passed to child view as an (observable) object
}
}
//Child view
struct DemoSettingsView: View {
//Parameters
var settings : DemoSettings // <- settings accepted from parent as an object
//Body
var body: some View {
@Bindable var settings = settings // <- Here, get a binding to the observable settings object
Text("Selected mode: \(String(describing: settings.currentSelection).capitalized)")
.foregroundStyle(settings.currentSelection.color)
Form {
Picker("Mode", selection: $settings.currentSelection) { // <- use the binding for the selection parameter
Text("Green")
.tag(ColorOptionEnum.green)
Text("Blue")
.tag(ColorOptionEnum.blue)
}
}
}
}
#Preview {
DemoSettingsRootView()
}
本文标签:
版权声明:本文标题:swift - Does anyone know why Picker from my view file won't accept the binding version of an observable object property 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738299200a2073524.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
@State
for the settingsViewModel property – Joakim Danielson Commented Jan 26 at 19:24@Observable
macro relies on reference semantics to track changes to properties, which is a behavior inherent to classes and not structs. Also, you would get an error if trying to apply the@Observable
macro to a struct - Documentation for Observation framework – Andrei G. Commented Jan 26 at 21:25