这是一个,
import SQLite var r:[[Any]] = [] do { if let stmt = try local.db?.prepare(q) { r = Array(stmt) } else { print("woe in sql?") } } catch { return [] }
电话
r = Array(stmt)
使表达从隐含裹挟"绑定?去任何.
事实上,我不知道如何提供默认值以避免此警告,强制解包该值以避免此警告,或者甚至使用"as Any"显式转换为Any以使此警告静音.:o
这是一个重现相同警告的自包含示例:
struct Binding {} struct Statement : IteratorProtocol, Sequence { func next() -> [Binding?]? { return nil } } let stmt = Statement() let r: [[Any]] r = Array(stmt) // warning: Expression implicitly coerced from 'Binding?' to Any.
相关有趣的问题:
为什么编译器......
...似乎不知道行号,有这样的问题?事实上:为什么只有在编译后才会出现警告?
在编译之前,当您键入时,大多数警告都会出现在IDE中.
此警告似乎(a)仅在编译期间已知并且(b)编译器不知道行号.
怎么会这样?有什么不同?
您正在使用Array
的顺序初始化器,它具有签名:
init(_ s: S) where S : Sequence, Element == S.Iterator.Element
因为你输入的r
是[[Any]]
,Element
是[Any]
.但是,您传入的序列有一种Iterator.Element
类型[Binding?]
.因此,你含蓄地强迫Binding?
来Any
,并按照SE-0140,这将调用一个警告-因为你失去的内部元素,这是潜在的不良的可选性.
正如提案所说,沉默这一警告的一种方法是添加一个明确的as Any
演员.在您的情况下,这可以通过使用嵌套来实现map(_:)
:
r = stmt.map { $0.map { $0 as Any } }
这不应该是任何更昂贵比使用Array
的顺序初始化器,由于事实上,在所有的内部元件散步会在两种情况下需要做,由于抽象类型的值如何存储斯威夫特(见区别这问答更多信息).
但是,真的,你应该问自己是否r
应该是类型[[Any]]
.我没有理由你不应该只是输入它[[Binding?]]
.这样做既可以消除警告,也可以提供更好的类型安全性.