【问题标题】:SwiftUI Optional TextFieldSwiftUI 可选文本字段
【发布时间】:2019-11-23 02:13:10
【问题描述】:

SwiftUI 文本字段可以与可选绑定一起使用吗?目前这段代码:

struct SOTestView : View {
    @State var test: String? = "Test"

    var body: some View {
        TextField($test)
    }
}

产生以下错误:

无法将“Binding”类型的值转换为预期的参数类型“Binding

有没有办法解决这个问题?在数据模型中使用 Optionals 是一种非常常见的模式——事实上它是 Core Data 中的默认设置,所以 SwiftUI 不支持它们似乎很奇怪

【问题讨论】:

  • TextField 需要 Binding,而不是 Binding。所以看起来你不能。您能否详细说明为什么需要这种绑定?
  • 你能用空字符串代替吗? @State var test = ""?如果不是,那么当您的字符串为nil 时,您希望TextField 做什么?
  • 是的 - 问题是核心数据创建 NSManaged 字符串作为可选
  • 提交了反馈助理报告,请求可选绑定,FB7619680。
  • 勾选模型中属性的默认字符串

标签: swiftui


【解决方案1】:

最终 API 不允许这样做 - 但有一个非常简单且通用的解决方法:

extension Optional where Wrapped == String {
    var _bound: String? {
        get {
            return self
        }
        set {
            self = newValue
        }
    }
    public var bound: String {
        get {
            return _bound ?? ""
        }
        set {
            _bound = newValue.isEmpty ? nil : newValue
        }
    }
}

这允许您在保持可选的同时使其与绑定兼容:

TextField($test.bound)

【讨论】:

  • 这很棒,因为它完全有效!我觉得必须有更好的方法,因为Binding 有一个optional initializer。我只是不知道如何将它与 Swift 速记一起使用。
  • 这是一个更好的答案,因为它不那么冗长。
【解决方案2】:

没错,目前 SwiftUI 中的 TextField 只能绑定到 String 变量,而不是 String?。 但是您始终可以像这样定义自己的Binding

import SwiftUI

struct SOTest: View {
    @State var text: String?

    var textBinding: Binding<String> {
        Binding<String>(
            get: {
                return self.text ?? ""
        },
            set: { newString in
                self.text = newString
        })
    }

    var body: some View {
        TextField("Enter a string", text: textBinding)
    }
}

基本上,您将TextField 文本值绑定到这个新的Binding&lt;String&gt; 绑定,然后绑定将其重定向到您的String? @State 变量。

【讨论】:

    【解决方案3】:

    您可以添加此运算符重载,然后它就像不是绑定一样自然地工作。

    func ??<T>(lhs: Binding<Optional<T>>, rhs: T) -> Binding<T> {
        Binding(
            get: { lhs.wrappedValue ?? rhs },
            set: { lhs.wrappedValue = $0 }
        )
    }
    

    这将创建一个 Binding,如果它不是 nil,则返回运算符值的左侧,否则从右侧返回默认值。

    设置时只设置 lhs 值,而忽略与右侧有关的任何内容。

    可以这样使用:

    TextField("", text: $test ?? "default value")
    

    【讨论】:

    • 这绝对是天才!!!很棒的解决方案!我不明白,为什么 SwiftUI 不支持开箱即用...
    • 这个函数在哪里写的?
    • @johndoe 就像一个全局函数。这只是一个运算符重载
    • @johndoe 你创建了一个新的 swift 文件,他的第一行是“import SwiftUI”,然后在下面粘贴他的代码。
    • 我为什么会收到“'??' 的重新声明无效”错误?我正在使用 XCode 12.4 和 Swift 5。
    猜你喜欢
    • 1970-01-01
    • 2021-11-14
    • 2021-10-09
    • 2021-01-06
    • 1970-01-01
    • 1970-01-01
    • 2021-02-18
    • 2020-12-20
    • 2020-07-27
    相关资源
    最近更新 更多