如果我有带签名的元组,(String, Bool)则无法将其强制转换为(String, Any)。编译器说:
(String, Bool)
(String, Any)
错误:无法表示元组转换((String,Bool)’到’(String,Any)’
但这应该可行,因为Bool可以安全地Any使用它as。如果执行类似的操作,几乎会引发相同的错误:
Bool
Any
as
let any: Any = ("String", true) any as! (String, Any) // error any as! (String, Bool) // obviously succeeds
错误:
无法将类型’(Swift.String,Swift.Bool)’的值强制转换为’(protocol <>,protocol <>))
那么,有什么变通办法,尤其是对于第二种情况?因为您甚至无法转换Any为(Any, Any)可以分别转换元素的任何元组。
(Any, Any)
即使元组可以包含类型,也不能强制转换。例如:
let nums = (1, 5, 9) let doubleNums = nums as (Double, Double, Double) //fails
但:
let nums : (Double, Double, Double) = (1, 5, 9) //succeeds
您的解决方法是强制转换单个元素,而不是元组本身:
let tuple = ("String", true) let anyTuple = (tuple.0, tuple.1 as Any) // anyTuple is (String, Any)
这是Swift文档指出的原因之一:
元组对于相关值的临时组很有用。它们不适合创建复杂的数据结构。如果您的数据结构可能会在临时范围之外继续存在,则将其建模为类或结构,而不是元组。
我认为这是一个实现限制,因为元组是像函数一样的 复合类型 。同样,您不能创建元组的扩展名(例如extension (String, Bool) { … })。
extension (String, Bool) { … }
如果您实际上使用的是会返回的API (String, Any),请尝试将其更改为使用类或结构。但是,如果您无力改善API,则可以switch使用第二个元素的类型:
switch
let tuple : (String, Any) = ("string", true) switch tuple.1 { case let x as Bool: print("It's a Bool") let boolTuple = (tuple.0, tuple.1 as! Bool) case let x as Double: print("It's a Double") let doubleTuple = (tuple.0, tuple.1 as! Double) case let x as NSDateFormatter: print("It's an NSDateFormatter") let dateFormatterTuple = (tuple.0, tuple.1 as! NSDateFormatter) default: print("Unsupported type") }
如果API返回Any并且不能保证元组为(String, Any),那么您就不走运了。