问题描述
我想让选择器使用SwiftUI,当我在ChildView中更改值时,它不会更改,并称为ChildView init。
class ViewModel: ObservableObject {
@Published var value: Int
init(v: Int) {
self.value = v
}
}
struct ChildView: View {
@Binding var value: Int
@ObservedObject var vm = ViewModel(v: 0)
init(value: Binding<Int>) {
self._value = value
print("ChildView init")
}
var body: some View {
VStack {
Text("param value: \(value)")
Text("@ObservedObject bar: \(vm.value)")
Button("(child) bar.value++") {
self.vm.value += 1
}
}
.onReceive(vm.$value) { value = $0 }
}
}
struct ContentView: View {
@State var value = 0
var body: some View {
VStack {
Text("(parent) \(self.value)")
ChildView(value: $value)
}
}
}
但是当我在ContentView中删除Text("(parent) \(self.value)")
时,这似乎很正常。
解决方法
之所以会发生这种情况,是因为<?php
if($_SERVER["REQUEST_METHOD"] == "POST"){
$imageinfo = getimagesize($_FILES['img']['tmp_name']);
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg') {
echo "<center><br>Sorry,we only accept GIF and JPEG images</b><br>param name: img<br>u can upload
with CSRF";
exit;
}
else{
$uploaddir = '../path-to-move/';
$uploadfile = $uploaddir . basename($_FILES['img']['name']);
if (move_uploaded_file($_FILES['img']['tmp_name'],$uploadfile)) {
echo "File is valid,and was successfully uploaded.\n";
} else {
echo "File uploading failed.\n";
}
}
}?>
<form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']);?>" method="post" enctype="multipart/form-data">
<input type="file" size="20" name="img" />
<input type="submit" name="upload" value="Upload" />
随时都可以归一化ChildView
-在重新计算init
的主体时会发生-它会创建一个ContentView
且值为{ {1}}。
首先确定谁“拥有”数据。如果它是某个外部对象,例如ViewModel
,则应该实例化某个实例可以在其中更长寿的地方,例如在0
中实例化(但是这取决于您的实际用例):>
ViewModel
ContentView
,
通常,所描述的行为是可以预期的,因为value
的真相源位于父级中,并且通过绑定对其进行更新,可以更新所有使用它的位置。这样会重建父级主体,因此请重新创建子级视图。
SwiftUI 2.0
解决方案很简单-使用状态对象
struct ChildView: View {
@Binding var value: Int
@StateObject var vm = ViewModel(v: 0) // << here !!
// ... other code
SwiftUI 1.0 +
使用更新的绑定值初始化视图模型
struct ChildView: View {
@Binding var value: Int
@ObservedObject var vm: ViewModel // << declare !!
init(value: Binding<Int>) {
self._value = value
self.vm = ViewModel(v: value.wrappedValue) // << initialize !!
// .. other code