在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)
有人可以解释这里发生了什么吗?
我不明白为什么添加这一行代码会有所作为。
print(“ HELLO”)
我希望perif的类型为CBPeripheral,而不是错误消息所述的[CBPeripheral]。
答案 0 :(得分:4)
如其他答案和注释中所述,使用forEach
或for ... in
是遍历数组的正确方法。
但是要回答您的问题并解释为什么那些看似相同的代码片段的行为会有所不同:这是由以下事实共同造成的:
[CBPeripheral]!
是一个隐式展开的可选(IUO),由于Swift 3,如果可能的话,它们被视为常规的可选。比较
func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U?
bodies of multi-statement closures don't participate in type inference。
在“单一陈述”中
_ = 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")
}
但是-正如已经说过的-在这种特殊情况下,有更好的解决方案。
答案 1 :(得分:2)
map
在Swift(和其他地方)中的工作方式是可以将输入从一种类型映射(改变)到另一种类型。因此,根据您的情况,您将在map
上调用[CBPeripheral]
,对于每个元素,map
函数将返回另一个值。因此,如果identifier
是String
,则最终将得到一个字符串数组。
这就是它的工作方式。
但是:)
在您的情况下,您已经定义了映射功能,
(perif) -> Void
这意味着您将遍历数组并调用map,并且该函数不会返回任何内容。这意味着结果将是一个填充有Void值的数组。
因此,正如其他人在评论中所建议的那样,如果您只想检查cbPerifList
的内容,则最好像这样使用for in
循环
for cbPerif in cbPerifList {
print(cbPerif.identifier)
}
但是,如果您有兴趣获取CBPeripherals
的名称数组,则可以执行以下操作
let names = cbPerifList.map { $0.identifier }
对以上内容的评论:要详细了解我们如何才能最终完成编写{ $0.name }
,请查看Swift文档中有关Closures或this answer的章节>
希望对您有帮助。