微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何修复 TextField Binding <String> 以在 SwiftUI 中显示和编辑

如何解决如何修复 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 ?? "" 时,我总是收到这样的错误

enter image description here

然后,当我使用 ? 修复它时,我会收到更多这样的错误

enter image description here

我陷入了这个错误循环,使用 force unwrap 会使应用程序崩溃。我有名称更多的变量,所以我不能在响应中只包含 self.name = response.name ?? ""。我该如何解决这个问题?

如有任何建议,我们将不胜感激。

解决方法

TextField 需要一个 Binding,而不仅仅是一个 String。因此,当您在 "" 为零的情况下提供它 Binding 时,您最终会得到非等价类型(Binding<String>String)。

要解决这个问题,您可能需要创建一个自定义绑定来处理 datanil 的情况。

这是一种可能的解决方案:


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 举报,一经查实,本站将立刻删除。