如何解决如何修复 TextField Binding <String> 以在 SwiftUI 中显示和编辑
我想在 TextField
中显示文本并能够对其进行编辑。但是我在绑定它时遇到了问题。这是我的代码:
struct DataView: View {
@Observedobject private var dataPresenter = DataPresenter()
var body: some View {
vstack {
TextField("Name",text: $dataPresenter.data?.name ?? "") // This is the error
}
.onAppear(perform: {
dataPresenter.getData()
})
}
}
class DataPresenter: ObservableObject {
@Injected private var getDataInteractor: GetDataInteractor
@Injected private var cancellables: Set<AnyCancellable>
@Published var data: GetDataResp?
func getData() {
getDataInteractor.execute()
.sink { error in
print("Error:",error)
} receiveValue: { response in
if response.errorCode == "00" {
print(response)
self.data = response
}
}
.store(in: &cancellables)
}
}
struct GetDataResp: Codable,Equatable {
var name : String?
var address : String?
var email : String?
enum CodingKeys: String,CodingKey {
case name = "name"
case address = "address"
case email = "email"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decodeIfPresent(String.self,forKey: .name)
address = try values.decodeIfPresent(String.self,forKey: .address)
email = try values.decodeIfPresent(String.self,forKey: .email)
}
}
当我不在 ?
中使用 $dataPresenter.data.name ?? ""
时,我总是收到这样的错误:
然后,当我使用 ?
修复它时,我会收到更多这样的错误:
我陷入了这个错误循环,使用 force unwrap
会使应用程序崩溃。我有比名称更多的变量,所以我不能在响应中只包含 self.name = response.name ?? ""
。我该如何解决这个问题?
如有任何建议,我们将不胜感激。
解决方法
TextField
需要一个 Binding
,而不仅仅是一个 String
。因此,当您在 ""
为零的情况下提供它 Binding
时,您最终会得到非等价类型(Binding<String>
与 String
)。
要解决这个问题,您可能需要创建一个自定义绑定来处理 data
为 nil
的情况。
这是一种可能的解决方案:
struct DataView: View {
@ObservedObject private var dataPresenter = DataPresenter()
var body: some View {
VStack {
Text(dataPresenter.data?.name ?? "Empty")
TextField("Name",text: dataPresenter.nonOptionalNameBinding())
}
}
}
struct GetDataResp {
var name : String
}
class DataPresenter: ObservableObject {
@Published var data: GetDataResp?
func nonOptionalNameBinding() -> Binding<String> {
.init {
return self.data?.name ?? ""
} set: { newValue in
if self.data == nil {
self.data = GetDataResp(name: newValue)
} else {
self.data?.name = newValue
}
}
}
}
您可能需要根据您的需要在 set:
部分中以不同方式处理这种情况。而且,当然,我删掉了 GetDataResp
,我假设它比我在那里的内容更详细,但这应该可以帮助您入门。
更新,基于评论:
struct GetDataResp: Codable,Equatable {
var name : String?
var address : String?
var email : String?
}
struct DataView: View {
@ObservedObject private var dataPresenter = DataPresenter()
var body: some View {
VStack {
Text(dataPresenter.data?.name ?? "Empty")
TextField("Name",text: dataPresenter.nonOptionalBinding(keyPath: \.name))
TextField("Address",text: dataPresenter.nonOptionalBinding(keyPath: \.address))
TextField("Email",text: dataPresenter.nonOptionalBinding(keyPath: \.email))
}
}
}
class DataPresenter: ObservableObject {
@Published var data: GetDataResp?
func nonOptionalBinding(keyPath: WritableKeyPath<GetDataResp,String?>) -> Binding<String> {
.init {
return self.data?[keyPath: keyPath] ?? ""
} set: { newValue in
if self.data == nil {
self.data = GetDataResp()
}
self.data?[keyPath: keyPath] = newValue
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。