1

我是 Swift 新手,正在尝试构建计算器的初学者项目。我知道“display.text”返回一个可选字符串,其中的字符串值必须用“!”展开 在它可以使用之前。

但是,我注意到“display.text”只需要解包一次,然后可以多次使用而无需再次解包。这对于 Swift 可选值是真的吗?我在哪里可以找到有关此事的一些指导方针?

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var display: UILabel!

    var userIsInTheMiddleOfTypingANumber = false

    @IBAction func appendDigit(sender: UIButton) {
        let digit = sender.currentTitle!
        if userIsInTheMiddleOfTypingANumber {
            display.text = display.text! + digit
        } else {
            display.text = digit
            userIsInTheMiddleOfTypingANumber = true
        }
    }
4

3 回答 3

2

解开可再次使用的可选项的两个标准选项:

1)如果让

if let unwrappedValue = someOptional {
  // unwrappedValue can be used only inside this block of code
}

2) 守卫

guard let unwrappedValue = someOptional else { return } 
/// unwrappedValue can be used as long as it is in scope
于 2016-02-26T10:22:46.150 回答
1

尝试这个。

guard let displayText = display.text else {
    // handle the case when optional has nil value
}

// In this scope you can use non-nil value of display.text as displayText.
print("displayText = \(displayText)")

这是您在展开一次后可以使用可选值的方式。另一种更简单的方法是只使用而不是guard-let.

if let displayText = display.text else {
    // safely unwrapped
}

希望有帮助!

检查此链接以获得更多帮助。

于 2016-02-26T10:21:54.807 回答
0

您通常应该避免强行解开可选项(使用 operator !),因为这将在可选项 contains 的情况下产生运行时异常nil。下面遵循一些技术来处理选项的展开。

可选绑定

请注意,如果您将其解包并将其分配给另一个非可选变量到相同的固有类型,那么您可以“解包一次然后多次使用”的唯一方法。

这是使用可选绑定时所做的:

/* Example setup */
let display: UILabel = UILabel()
let digit = "1"

/* optional binding using if-let:
   _assign_ unwrapped value (if non-nil) to 'unwrapped' */
if let unwrappedText = display.text {
    // 'unwrapped' resides in scope inside of the if-let block
    display.text = unwrappedText + digit
}
else {
    display.text = digit
}

/* optional binding using guard-let-else:
   _assign_ unwrapped value (if non-nil) to 'unwrapped' */
func foo(disp: UILabel, _ dig: String) {
    guard let unwrappedText = display.text else {
        display.text = digit
        return
    }
    // 'unwrapped' resides in scope outside of the guard-let-else block
    display.text = unwrappedText + digit
}
foo(display, digit)

无合并运算符

如果您不想使用条件绑定显式分配展开的值,则可以使用nil 合并运算符进行安全展开。

/* nil coalescing operator */
display.text = (display.text ?? "") + digit

但是,现在您可以以半可选绑定方式使用 nil 合并运算符;如果可选项为 nil,则分配可选项或某个默认值的展开值:

let metaUnwrapped = display.text ?? ""

不可变metaUnwrapped将在其范围内可用,并包含display.text(at assignment)nil的值,如果不是,或者默认值"",如果display.textnil在分配。您可以在上面的可选绑定示例中以metaUnwrapped与 immutable 相同的方式使用:unwrapped

display.text = metaUnwrapped + digit

可选链接

对于您的问题,这有点偏离基础,但是由于我们讨论的是可选和展开的主题,所以我不妨提一下可选链接

鉴于可选属性不是 ,可选链接可用于访问某些可选属性的属性nil。例如,假设您想计算 中的字符数display.text,但自然只有当可选.text属性为非时nil。在这种情况下,可选链接与 nil 合并运算符相结合可能是一种合适的选择方法:

let numCharacters = display.text?.characters.count ?? 0
    /* if text != nil, returns character count; otherwise, by
       nil coalescing operator, returns 0 /*
于 2016-02-26T11:44:22.467 回答