swift - 如何在 SwiftUI 中使用 inout 而不是 Binding?

标签 swift swiftui

我想知道我是否可以通过 inout 而不是 Binding 使我的 View 函数绑定(bind)自身,是否有可能为我们提供正确/更好的语法?正确知道我得到编译时错误:

Modifying state during view update, this will cause undefined behavior.

这对我来说是可以理解的,我想也许我在这项工作中使用了错误的语法。

PS:我完全了解 Binding 及其用例,如果我们也可以用 inout 解决这个问题,请尝试找到答案。


func TextView(inPutValue: inout Bool) -> some View {

    return Text("Hello")
        .onTapGesture { inPutValue.toggle() }
    
}

用例:

struct ContentView: View {

    @State private var isOn: Bool = true

    var body: some View {
        
        TextView(inPutValue: &isOn)
 
    }
    
}


更新:

import SwiftUI

struct ContentView: View {

    @State private var value: Int = Int() { didSet { print(value.description) } }

    var body: some View {

        Button("update State via inout") { inoutFunction(incomingValue: &value) }
        
    }

}

func inoutFunction(incomingValue: inout Int) { incomingValue += 1 }

最佳答案

这里不能使用inout的原因是inout有一个copy-in-copy-out。行为。该值作为副本传递给函数,一旦函数返回,修改后的副本就会被复制回来。您不应该将其视为按引用传递,认为它可以作为优化以这种方式实现。

现在知道了,Swift 编译器禁止您在转义闭包中使用 inout 参数很有意义,例如在 onTapGestureinPutValue。毕竟,修改后的 inPutValue 只会在 TextView 返回时复制回来,而不是在有人点击它时复制回来,因此无论您在 onTapGesture 中对其进行什么修改TextView 的调用者根本不可见。另见 this answer .

因此,一旦 TextView 返回,值就会被复制回调用者。如错误消息所述,不允许在计算 body 时直接修改 @State(即“在 View 更新期间”)。

现在让我们看一下Button 的情况。请注意,这次对 inoutFunction(incomingValue: &value) 的调用发生在按钮的点击处理程序中,而不是在 body 中 - 这意味着 value 将按下按钮时写入。这是允许的。

您可以通过添加闭包参数使您的 TextView 具有与 Button 的初始化程序类似的形式:

func TextView(update: @escaping () -> Void) -> some View {

    return Text("Hello")
        .onTapGesture(perform: update)
    
}

注意这里根本没有inout,就像Button.init中没有inout一样。

然后您可以使用 inout 参数编写您的函数:

func inoutFunction(_ b: inout Bool) {
    b.toggle()
}

并使用它:

@State private var isOn = true

var body: some View {
    TextView { inoutFunction(incomingValue: &isOn) }
}

请注意,您根本不需要 inout

TextView { isOn.toggle() }

关于swift - 如何在 SwiftUI 中使用 inout 而不是 Binding?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66939775/

相关文章:

SwiftUI:onDelete 无法正确更新 UI

swift - 在 SwiftUI 中的 Scrollview(列表的替代方案)中使用 VStack 时的性能

ios - 如何将 rx_tap (UIButton) 绑定(bind)到 ViewModel?

ios - UITableViewAutomaticDimension 不适用于自定义表格单元格

network-programming - 当发布者失败时,合并接收器无法完成

ios - 如何在 SwiftUI 中关闭选项卡 View Root View 的呈现 View ?

ios - 更改 CoreData 记录,SwiftUI

ios - Swift UIView 自定义 View 在 ViewController 操作后不会更新

swift - 在开始时创建数百个 UIImage 并让它们在 Swift 中的任何位置可用的最佳方法是什么?

objective-c - 禁用 WebView 中的拖动