【问题标题】:Why was UITextField's text property changed to an optional in Swift 2?为什么 UITextField 的 text 属性在 Swift 2 中改为可选?
【发布时间】:2015-12-13 18:33:40
【问题描述】:

根据UIKit diff document,在ios9/Swift 2中

var text: String! 变成了var text: String?

根据documentation for UITextField 的说法

This string is @"" by default.

我不明白此更改的目的。如果文本字段完全存在,该属性不应该始终为空字符串吗?这个字段在什么时候返回一个空字符串?一旦用户与之交互?一旦它被添加到视图层次结构中?什么时候返回nil

如果文本字段首先存在,那么假设文本属性也存在是否总是安全的?这似乎会导致大量查找/替换 .text.text!

我没有看到文档中提到它的位置,所以也许有人有一些背景故事或帮助说明为什么会发生这种变化。

【问题讨论】:

  • 更多细节,我只是设置了一个游乐场并制作了一个 UITextField。 text 属性实际上是一个 optional 空字符串。我现在更困惑了
  • Apple 似乎不相信他们的 API 总是为我们的 text 属性提供一个非零值,所以他们只是将guard 的责任转移给了我们。不喜欢这种方法。

标签: ios swift uitextfield uikit swift2


【解决方案1】:

简而言之,(回答标题)不是。

详细说明:

对我来说,将它作为不强制解包的可选选项更有意义。 Apple 正在推动开发人员不要只使用optional!,并且只有将相同的规则应用于 API 才有意义。

这样做的原因是它可以为nil,如果用?! 声明来运行代码,它没有任何区别。使用! 实际上只是删除了 Xcode 中非常方便的警告,尤其是在涉及 API 代码时。如果您没有意识到它实际上是可选的,那您只是在自找麻烦。

现在使用 guard 检查 nil 也变得更好了,您可以将其与检查 "" 链接起来,因此实际上并没有更多的工作。

一般来说,可选值更好,因为 nil 不使用内存。我们得到的选项越多,我们的应用程序就越轻。 而且它看起来还不错,也不会增加厄运金字塔。

此示例将两个字符串都作为参数,删除 func 参数中的?,Xcode 将在那里警告您。

这部分我忘了直接回答: 当您将其设置为 nil 时,它变为 nil,您可能会这样做以节省一点内存。将其设置为 nil 而没有 xcode 警告您正确处理它是没有意义的。 => 这是不可能的...

var forcedUnwrappedString : String! = ""
var optionalString : String? = ""

forcedUnwrappedString = nil
optionalString = nil

func doSomethingWithString(string : String?) -> String? {
    guard var unwrappedString = string else {
        // error handling here
        return nil
    }
    let tempString = unwrappedString + "!"

    return tempString
}

func doSomethingUnsafeWithString(string : String) -> String {

    let tempString = string
    return tempString

}

var newString = doSomethingWithString(optionalString)
var newString2 = doSomethingWithString(forcedUnwrappedString)

newString = doSomethingUnsafeWithString(optionalString!) // this will crash without a warning fro xcode
newString2 = doSomethingUnsafeWithString(forcedUnwrappedString) // this will crash without a warning fro xcode

更新:

UITextfield 的 text 属性有一个 setter,在 nil 的情况下始终设置为 "",文档或 UIKit .h 文件中没有任何信息。

var textField = UITextField(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
var string = textField.text // string = ""
textField.text = nil
string = textField.text // string = ""

【讨论】:

  • 我认为您没有在这里解析我的问题。我绝对理解选项的价值。我特意询问UITextField,它是text:String 属性。在 iOS 9 中,它是可选的,而在此之前它不是,并且文档仍然说它将始终是一个空字符串。测试操场证实了这一点。我想知道为什么会改变这一点,或者是否有一些用例使它变得有价值。
  • 我确实阅读了你的整个问题,我也没有费心解释什么是可选的。我解释了为什么 Apple 将其从强制解包选项更改为不是因为您的问题指出它之前是强制解包选项并且是 Swift2 中的常规选项。现在在你的评论中你说它以前不是可选的?
  • "it was a forced unwrapped optional before" 回答了为什么他们让它不隐藏它的不安全行为。但是为什么一开始是可选的呢?我用一个 UITextField 做了一个简单的测试项目,并设置每个 deletgate 函数来打印出文本字段的文本属性。始终可选(“”)。然后我在textFieldShouldBeginEditing: 中添加了一个textField.text = nil,但在分配报告它仍然是可选的(“”)之后立即打印出textField.text。因此,setter 强制字符串始终至少为空字符串。例如,它永远不会是nil,即使它被分配了那个值。
  • 如果它永远不会变成 nil,那么强制解包是否安全?我试图从UITextField 中获取文本,如果它是空字符串,请改用占位符。向此逻辑添加可选的检查/解包使其非常具有挑战性...
  • @NicolasMiari 对于您的情况,这应该没问题,因为听起来您正在使用字符串。但是,如果您强制解开 UITextField,则立即尝试将其转换为 int,例如Int(textField.text!) 你会得到 nil 而不是空字符串。在这种情况下,我建议使用if let number = Int(textField.text!) { ... }
【解决方案2】:

解决此问题的一种简单方法是创建 UITextField 的扩展并使用它而不是 .text 属性。

extension UITextField {
    var unwrappedText: String {
        return self.text ?? ""
     }
}

现在你可以说 textfield.unwrappedText 而不必担心选项。 (当然这只是为了读取值)。

【讨论】:

    【解决方案3】:

    正如 Menke 自己所说,实际上不可能将 text 设置为 nil。显然,Apple 希望它被记录为可空的,尽管目前的实现,对我来说这没有任何意义——我的意思是对我来说没有足够的意义。问题是,Apple 做出这样的决定绝对没有“错误”,但这是对每个人都优雅的做事方式吗?显然不是。如果您不同意他们的观点,请不要担心,您可以对 Apple 的某些决定保留您的意见。

    那么这个改变的目的是什么?也许他们制定了一条内部规则,即出于一致性考虑,永远不要让 UIKits 组件的任何属性不可为空。也许他们在理论上认为,在某些极端情况下,由于内存压力,可能会释放 text 属性。不管它们是什么,我不认为它们是有效的,但我们必须服从。然而,这并不能使我成为一个狂热的粉丝。

    【讨论】:

      猜你喜欢
      • 2014-11-12
      • 1970-01-01
      • 2011-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-20
      • 2023-01-13
      相关资源
      最近更新 更多