簡體   English   中英

如何修復 TextField 綁定<string>在 SwiftUI 中顯示和編輯</string>

[英]How to fix TextField Binding <String> to show and edit in 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?? "" $dataPresenter.data.name?? "" ,我總是收到這樣的錯誤:

在此處輸入圖像描述

然后,當我用? ,我得到更多這樣的錯誤:

在此處輸入圖像描述

我陷入了這個錯誤循環,使用force unwrap會使應用程序崩潰。 我有比名字更多的變量,所以我不能只是self.name = response.name?? "" self.name = response.name?? ""在響應中。 我怎么能解決這個問題?

任何建議,將不勝感激。

TextField需要一個Binding ,而不僅僅是一個String 因此,當您在Binding為 nil 的情況下提供""時,您最終會得到非等效類型( Binding<String> vs 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
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM