Reputation: 1
I am trying to programminglly add a UI_Element struct to UI_Group array triggered by a socketio listening event, but there is an alert:
"Accessing State's value outside of being installed on a View. This will result in a constant Binding of the initial value and will not update."
It seems that I shouldn't access a state's value(item.$name) in ContentView struct, but I don't know how to fix it~QQ
Also, I tried to move the UI_element struct into Service class or ContentView struct, and it couldn't work either.
final class Service: ObservableObject {
private var manager = SocketManager(socketURL: URL(string: "http://x.x.x.x")!, config: [.log(true), .compress])
@Published var messages = [String]()
@Published var UI_Group = [UI_Element]()
init() {
let socket = manager.defaultSocket
socket.on(clientEvent: .connect) {(data, ack) in
print("Connected")
socket.emit("Python Server Port", "Hi Python Server!")
}
socket.on("iOS Client Port") {[weak self] (data, ack) in
if let data = data[0] as? [String: String],
let rawMessage = data["msg"] {
DispatchQueue.main.async {
//self?.messages.append(rawMessage)
switch rawMessage {
case "0":
print("新增中")
self?.UI_Group.append(UI_Element())
if self?.UI_Group != nil {
guard let num_element = self?.UI_Group.count else {
return print("無法新增")
}
print("已新增\(num_element)個元素")
}
default:
print("hello")
}
}
}
socket.connect()
}
}
struct ContentView: View {
@ObservedObject var service = Service()
var body: some View {
VStack{
ForEach(service.UI_Group, id: \.id){ item in
TextField("Please enter text.", text: item.$name)
.padding()
.accessibilityLabel("請輸入元素名稱")
.textFieldStyle(.roundedBorder)
.offset(x: CGFloat(item.center_x), y: CGFloat(item.center_y))
}
}
}
}
struct UI_Element: Identifiable {
let id = UUID()
let type:Int
@State var name = ""
@State var center_x = 0
@State var center_y = 0
@State var ui_state = 0
init() {
self.type = 0
self.name = "請輸入元素名稱"
self.center_x = 50
self.center_y = 50
self.ui_state = 0
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Upvotes: 0
Views: 73
Reputation: 7754
Your assumption:
It seems that I shouldn't access a state's value(item.$name) in ContentView struct
is wrong. The message is because you are using @State in your model 'UI_Element'
Remove the @State wrappers. As the message says they are useless if they are not in a view.
Possible solution:
If you want to use your model in the ContentView with textfield you would need to make your struct 'UI_Element' a class and ObservableObject. Then use @Published on your name property.
Upvotes: 0