gpt4 book ai didi

ios - SwiftUI 中 $varName 和 _varName 有什么区别

转载 作者:搜寻专家 更新时间:2023-11-01 06:10:46 25 4
gpt4 key购买 nike

当您使用属性包装器时,您可以访问这两个 $varName_varName我真的不知道有什么区别。比如这里

import SwiftUI

struct ContentView: View {
@Binding var varName: String

var body: some View {
TextField("", text: $varName) //here you can also use `_varName`
}
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(varName: .constant("Hello world!"))
}
}
#endif

您可以同时使用 $varName_varName .这两个解决方案似乎是等价的。两个变量都是 Binding<String> .但是如果我需要这样的东西:

import SwiftUI

struct ContentView: View {
@Binding var varName: String

init(varName: Binding<String>) {
self.$varName = varName //ERROR
}

var body: some View {
TextField("", text: $varName)
}
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(varName: .constant("Hello world!"))
}
}
#endif

我会得到一个错误:

Cannot assign to property: '$varName' is immutable

我必须使用 _varName为了抑制错误:

struct ContentView: View {
@Binding var varName: String

init(varName: Binding<String>) {
self._varName = varName //this works fine
}

var body: some View {
TextField("", text: _varName)
}
}

他们仍然都是Binding<String> ,那么为什么以前的解决方案不起作用?根据 Apple ( https://developer.apple.com/videos/play/wwdc2019/415/ ) 的说法,编译器会将属性包装器变成两个东西。这:

@Binding var varName: String

变成:

//Compiler-synthesized code
var $varName = Binding<String> = Binding<String>()

public var varName: String {
get { $varName.wrappedValue }

set { $varName.wrappedValue = newValue }
}

$varName应该是 var ,那么为什么会出现上面的错误呢?而且,最重要的是,那是什么 _varName ?它从哪里来?

最佳答案

合成_varName property 是一个存储的、可设置的属性,它包含(在您的情况下)Binding<String> 的一个实例.

varName属性映射到包装器的 wrappedValue属性(property)。 Binding declares wrappedValue 像这样:

var wrappedValue: Value { get nonmutating set }

wrappedValuenonmutating set 声明, 合成 varName属性始终是可设置的(即使 self 不可变)。

合成$varName属性映射到包装器的 projectedValue属性,如果包装器有一个 projectedValue属性(property)。 Binding declares projectedValue 像这样:

var projectedValue: Binding<Value> { get }

projectedValue仅声明 get , 不是 get set , 你永远不能分配给 $varName .

Binding不需要需要提供 projectedValue属性,因为您可以使用 _varName得到Binding<String>目的。原因Binding声明一个 projectedValue属性是使$前缀对 Binding 的工作方式相同正如它对 State 所做的那样, ObservedObject , 和 EnvironmentObject .

关于ios - SwiftUI 中 $varName 和 _varName 有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58088988/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com