以编程方式更新 SwiftUI 中的状态

Update State in SwiftUI Programatically

提问人:Ryan 提问时间:11/16/2023 最后编辑:RudedogRyan 更新时间:11/17/2023 访问量:75

问:

我是 Swift 的新手,来自 React,我确信我对状态的看法是错误的。我有一个具有简单文本输入的视图。根据外部事件,我想更新此字段的内容以匹配当前的粘贴板内容。

struct ContentView: View {
    
    @State var input: String = ""
    
    var body: some View {
        HStack {            
            VStack( alignment:.leading, spacing: 16, content:{
                TextField("#000000", text: $input)
            })
            .padding()
        }
    }
    
    func update(){
        let pasteboard = NSPasteboard.general
        let firstItem = pasteboard.pasteboardItems![0];
        let string = firstItem.string(forType: NSPasteboard.PasteboardType(rawValue: "public.utf8-plain-text"))!
        NSLog(string);
        input = string;
    }
}

一切似乎都正常,除了没有更新调试器中的 Field 的内容(也没有更新状态变量),我可以看到调用函数时可以看到,但它不会影响 Field 内容。input = string

我只需要调用一些不同的 setState 函数吗?还是这不可能?

Swift SwiftUI 状态 文本字段

评论

0赞 Sweeper 11/16/2023
你在哪里打电话?update
0赞 vadian 11/16/2023
强烈建议不要强制解包和硬编码索引下标。 可以简化为 .这是 Swift,没有尾随分号。update()guard let string = NSPasteboard.general.string(forType: .string) else { return } input = string
0赞 Ryan 11/17/2023
此视图是 menuItem 的一部分。我从一开始就打电话,感觉有点骇人听闻。我所需要的只是每次打开菜单时更新粘贴板内容的文本字段,然后允许用户从那时起更改它。也许在视图本身上使用更好的事件?updateNSMenuDelegatemenuWillOpen

答:

0赞 malhal 11/16/2023 #1

body仅当设置了状态(如果之前已读取)时才调用。在这种情况下是不寻常的,通常表明您的层次结构或事实来源不正确,但是您可以通过伪造这样的阅读来修复它:View

struct ContentView: View {
    
    @State var input: String = ""
    
    var body: some View {
        let _ = input

仅供参考,不被认为是读法的原因是,是句法糖,即一对闭包。$inputBinding(get: {}, set {})

0赞 Ryan 11/17/2023 #2

谢谢大家,视图在隐藏时似乎没有设置状态变量,因此,如果我每次出现视图时简单地调用它,它就可以工作,而不是从显示视图的对象调用(同时显示视图):update

struct ContentView: View {
    
    @State var input: String = ""
    
    var body: some View {
        HStack {            
            VStack( alignment:.leading, spacing: 16, content:{
                TextField("#000000", text: $input)
            })
            .padding()
        }
        .onAppear {
            update()
        }
    }
    
    func update(){
        guard let string = NSPasteboard.general.string(forType: .string) else { return }
        input = string
    }
}