【问题标题】:Swift 4.2 weird -.map- behaviorSwift 4.2 奇怪的 -.map- 行为
【发布时间】:2019-01-13 10:02:35
【问题描述】:

我在 Swift 4.2 的集合上使用 .map 时遇到了一些问题。 这是正在发生的事情:

我有一个这样声明的属性:

var cbPerifList:[CBPeripheral]!

后面在我写代码的时候:

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
}

编译器看起来很开心,没有抱怨。

但是当我写的时候:

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
    print("HELLO")
}

编译器通过显示此消息来抱怨。

Value of type '[CBPeripheral]' has no member 'identifier'

在代码行上:print(perif.identifier)

有人能解释一下这里发生了什么吗?

  1. 我不明白为什么添加这行代码会有所不同。

    打印(“你好”)

  2. 我希望 perif 是 CBPeripheral 类型,而不是错误消息中所说的 [CBPeripheral]。

【问题讨论】:

  • 你最好在这里使用forEach而不是map。
  • 无法在操场上重现(Xcode 10.1),两个代码 sn-ps 都可以工作。另外,如果你只想打印标识符,你应该通过for-in或forEach来做,没有理由映射数组。

标签: swift collections


【解决方案1】:

如其他答案和 cmets 中所述,使用 forEach 或 for ... in 将是遍历数组的正确方法。

但要回答您的问题并解释为什么那些看似相同的代码 sn-ps 行为不同:这是由几个事实的组合造成的:

在“单语句”闭包中

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
}

编译器尝试从print 表达式推断闭包类型,并且为了对perif.identifier 进行类型检查,必须将IUO cbPerifList 解包到一个数组中。

在“多语句”闭包中

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
    print("HELLO")
}

编译器不会尝试从上下文推断闭包类型。因此cbPerifList 被视为常规可选,map() 是上述Optional.map 方法。在闭包内部,perif 具有展开的类型 [CBPeripheral]。这就是为什么perif.identifier 没有编译并显示错误消息的原因

“[CBPeripheral]”类型的值没有成员“标识符”

您可以通过显式类型注释“帮助”编译器

_ = cbPerifList.map { (perif: CBPeripheral) -> Void in
    print(perif.identifier)
    print("HELLO")
}

但是——如前所述——在这种特殊情况下有更好的解决方案。

【讨论】:

    【解决方案2】:

    map 在 Swift(和其他地方)中的工作方式是它可以将输入从一种类型映射(更改)到另一种类型。因此,在您的情况下,您将在 [CBPeripheral] 上调用 map 并且对于每个元素,map 函数将返回另一个值。所以,如果identifier 是String,你会得到一个字符串数组。

    它应该是这样工作的。

    但是:)

    在您的情况下,您已经像这样定义了映射函数

    (perif) -> Void
    

    这意味着您将遍历您的数组并调用 map,并使用一个不返回任何内容的函数。这意味着结果将是一个填充了 Void 值的数组。

    因此,正如其他人在 cmets 中建议的那样,如果您只想检查 cbPerifList 的内容,最好使用 for in 这样的循环

    for cbPerif in cbPerifList {
        print(cbPerif.identifier)
    }
    

    但是,如果您有兴趣获取 CBPeripherals 的名称数组,您可以这样做

    let names = cbPerifList.map { $0.identifier }
    

    对上述内容的评论:要了解更多关于我们如何最终只写 { $0.name } 的信息,请查看 Swift 文档中关于 Closures 的章节,或 this answer

    希望对你有所帮助。

    【讨论】:

      猜你喜欢
      • 2017-09-27
      • 1970-01-01
      • 1970-01-01
      • 2016-01-28
      • 2019-01-23
      • 2019-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多