以编程方式添加数组元素"Accessing State's value outside of being installed on a View."弹出警报



我正试图通过编程将UI_Element结构添加到由socketio侦听事件触发的UI_Group数组中,但出现警报:

"在视图上安装之外访问State的值。这将导致初始值的常量绑定,而不会更新">

我似乎不应该访问ContentView结构中的状态值(item.$name(,但我不知道如何修复它~QQ

此外,我试图将UI_element结构移到Service类或ContentView结构中,但它也无法工作。

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()
}
}

您的假设:

似乎我不应该访问ContentView结构中的状态值(item.$name(

错误。该消息是因为您正在模型"UI_Element"中使用@State

删除@State包装。正如信息所说,如果它们不在视野中,它们就毫无用处。

可能的解决方案:

如果您想在ContentView中使用带有文本字段的模型,则需要将结构"UI_Element"设置为类和ObservableObject。然后在您的name属性中使用@Published。

相关内容

最新更新