为什么 randomElement() return ?并不是?

Why does randomElement() return ?? and not?

我正在学习 Swift 和一些 iOS 开发。这是我的代码,我试图找出 XCode 抱怨的原因。

private func rollMyDice() {
    let diceRollImages = [
        UIImage(named: "DiceOne"),
        UIImage(named: "DiceTwo"),
        UIImage(named: "DiceThree"),
        UIImage(named: "DiceFour"),
        UIImage(named: "DiceFive"),
        UIImage(named: "DiceSix")
    ]

    diceOneImageView.image = diceRollImages.randomElement()
    diceTwoImageView.image = diceRollImages.randomElement()
}

所以在这种情况下,diceOneImageView.image = diceRollImages.randomElement()会抱怨无法将UIImage??赋值给UIImage?

ImageView.imageUIImage? 类型。我不明白的是为什么 randomElement() 这里是 returning UIImage??.

UIImage??是什么意思?我以为 ?? 是零合并运算符,所以我不确定为什么它是某些 return 类型的一部分。

同时阅读有关 randomElement() 的文档,它应该 return ?。所以在这种情况下,我希望 diceRollImages.randomElement() 到 return UIImage? 应该适合 diceOneImageView.image.

这里发生了什么?我知道我可以通过使用 ! 或使用 nil coalescing 等来修复它以使其工作。只是不明白发生了什么。

答案已经在评论中给出了:UIImage(named:) returns (optional) UIImage? 调用randomElement() optional 的结果是double optional ??

这是一个欢迎强制展开的好例子。

图像是应用程序包的一部分,在运行时是不可变的,如果其中之一丢失,应用程序将毫无用处。

声明diceRollImages

let diceRollImages = [
    UIImage(named: "DiceOne")!,
    UIImage(named: "DiceTwo")!,
    UIImage(named: "DiceThree")!,
    UIImage(named: "DiceFour")!,
    UIImage(named: "DiceFive")!,
    UIImage(named: "DiceSix")!
]

如果代码仍然崩溃,则会显示 设计 错误,可以立即修复。

你甚至可以强制展开 randomElement()! 因为数组是一个常量并且显然不是空的。

注意 UIImage(named:) 是一个可失败的初始化器,所以表达式 UIImage(named: "DiceOne") 等是 UIImage? 类型。这使得数组 diceRollImages 成为 [UIImage?] 类型。数组的每个 ElementUIImage?,或者写成 Optional<UIImage>.

如您所知,Optional 只是一个具有两种情况的枚举,.some.none(又名 nil)。数组的每个元素可以是:

  • .some(image),如果从名字
  • 成功创建了一个UIImage
  • .none,如果没有该名称的图像

randomElement 被声明为 return Element? (Optional<Element>),因为数组可能没有元素,因此不能给你一个随机元素。 randomElement returns:

  • .none,当数组为空时
  • .some(elementOfTheArray),当数组为non-empty且elementOfTheArray为数组中的随机元素时

回想一下 ElementdiceRollImages 的情况下是 Optional<UIImage>,并且数组元素 (elementOfTheArray) 可以具有值 .some(image).none.

因此,我们可以说 randomElement return 是一个 Optional<Optional<UIImage>> 类型的值,又名 UIImage??,它可能是以下三种情况之一:

  • .none当数组为空时
  • .some(.some(image))当数组为non-empty且随机选择数组中的一张successfully-created图像
  • .some(.none)当数组为non-empty且随机选取数组中未successfully-created张图片

由于您对图像数组进行了硬编码,因此您知道该数组不为空,因此 force-unwrap 可选的外层是安全的:

diceOneImageView.image = diceRollImages.randomElement()!