@State @Binding
2019-09-26 本文已影响0人
幸运者_Lucky
@State
和 RN
的一样, 就是 UI 和 数据的同步, 当值改变的时候 UI 同时改变
struct ContentView: View {
@State var text = "1"
var body: some View {
VStack {
Text(text)
.newStyle().padding()
Button(action: add, label: { Text("Add") })
}
}
func add() {
text = "2"
}
}
@Binding
现在 Swift
里面大多是值类型, @Binding
就是为了同步值类型, 不同页面传递的值类型属性, 被 @Binding
标记后, 前后使用同一个对象. 不会发生 Copy on Write
.
struct ContentView: View {
@State var text = "1"
var body: some View {
VStack {
Text(text)
CustomText(text: $text)
Button(action: add, label: { Text("Add") })
}
}
func add() {
withUnsafePointer(to: &text) {
print($0)
}
text = text + text
}
}
struct CustomText: View {
@Binding var text: String
var body: some View {
VStack {
Text(text)
Button(action: add, label: { Text("Button") })
}
}
func add() {
withUnsafePointer(to: &text) {
print($0)
}
text = text + text
}
}
通过上面代码运行可以看到, Text(text) CustomText(text: $text)
显示的内容是相同的, 无论改变哪个 var text
, 然后打印了一下两个 text
的地址, 发现他们的地址相同, 如下代码, 所以说 @Binding
前后两个值对象是同一个
struct ContentView: View {
@State var int = 0
@State var string = "0"
var body: some View {
VStack {
Text("\(int)")
Text(string)
CustomText(string: $string, int: $int)
Button(action: add, label: { Text("Add") })
}
}
func add() {
withUnsafePointer(to: &int) {
print("int: \($0)")
}
withUnsafePointer(to: &string) {
print("string: \($0)")
}
string = string + "0"
int += 1
}
}
struct CustomText: View {
@Binding var string: String
@Binding var int: Int
var body: some View {
VStack {
Text("\(int)")
Text(string)
Button(action: add, label: { Text("Button") })
}
}
func add() {
withUnsafePointer(to: &int) {
print("custom int: \($0)")
}
withUnsafePointer(to: &string) {
print("custom string: \($0)")
}
string = string + "0"
int += 1
}
}
custom int: 0x00007ffee4c1e410
custom string: 0x00007ffee4c1e3f8
int: 0x00007ffee4c1e410
string: 0x00007ffee4c1e3f8
struct
本身是无法通过 self
, 来修改自己的属性的, self
本身是不可修改的, 即为 let
, 但 @Binding var
修饰的属性可以在 struct
中, 通过self
修改, 因为调用的 set
方法标记为 nonmutating
, 具体细节请参考 @propertyWrapper
@Binding
的 wrappedValue
具体细节参考如下:
/// The value referenced by the binding. Assignments to the value
/// will be immediately visible on reading (assuming the binding
/// represents a mutable location), but the view changes they cause
/// may be processed asynchronously to the assignment.
public var wrappedValue: Value { get nonmutating set }