ios - 如何修复 TextField 绑定在 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)
}
}
当我不使用?
in 时$dataPresenter.data.name ?? ""
,我总是会收到这样的错误:
然后,当我用 修复它时?
,我会收到更多这样的错误:
我陷入了这个错误循环,使用force unwrap
会使应用程序崩溃。我有比名字更多的变量,所以我不能只self.name = response.name ?? ""
在响应中。我怎么能解决这个问题?
任何建议,将不胜感激。
解决方案
TextField
需要一个,而Binding
不仅仅是一个String
。因此,当您""
在Binding
为 nil 的情况下提供它时,您最终会得到非等效类型(Binding<String>
vs 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:
节中的情况。而且,当然,我 stubbed 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
}
}
}
推荐阅读
- python - 数独回溯求解器错误
- cordova - 配置“编译”已过时,已替换为“实现”
- amazon-web-services - Boto3 和 DynamoDB - 如何模拟聚合
- django - 如果条件为真,Django 在 ModelForm 中创建字段
- java - Orika 对象映射器未映射列表
- postgresql - 在 Linux Mint 20.1 Ulyssa 64 位上安装 PostgreSQL 12 和 PgAdmin4 时出现问题
- traefik - Traefik-通过fastapi网络服务器按路径路由
- python - AttributeError:“HTMLParser”对象没有属性“unescape”
- java - 尝试从 MySQL 数据库创建列表视图时出现解析器错误
- java - 在 Java 中运行 minimax connectM 时使数组索引越界