如果我在我的类中声明了一个隐式解包的可选项,然后我在类型为Dictionary
的{{1}}中引用它,则它不会被解包。为什么是这样?为什么[String : Any]
不是可选的,不强迫它解包?
Any
请注意,如果我将字典指定为var aString: String! = "hello"
var params : [String : Any] = [
"myString" : aString
]
print(params)
// This prints ["myString": Swift.ImplicitlyUnwrappedOptional<Swift.String>.some("hello")]
类型,它将被解包,但是当我需要[String : String]
中的多个类型时,这没有用。
答案 0 :(得分:10)
根据SE-0054规定的规则,IUO仅在需要其未打包类型的上下文中被强制解包。在您的情况下,IUO不需要强制解包,以便被强制转换为Any
(因为Any
可以代表任何值),所以它不是。
在这些Q&amp; As:
中更详细地讨论了这种行为您在字典中最终得到ImplicitlyUnwrappedOptional
值的事实是在最新的Swift快照中删除的遗留行为,将来您最终会得到Optional
值(因为IUO不再是一种类型)。
然而,这里需要注意的一件重要事情(我肯定会让人绊倒)是IUO的打印在4.1中发生了变化。
在Swift 4.0.3中,您的示例打印如下:
var aString: String! = "hello"
var params : [String : Any] = [
"myString" : aString
]
print(params)
// This prints ["myString": hello]
给你幻觉,强迫IUO在被强制解除Any
时被解开。然而,这就是如何在Swift 4.0.3中打印IUO - 如果它们有一个值,那么它们将打印为该值,否则它们将打印为nil
:
var aString: String! = nil
var params : [String : Any] = [
"myString" : aString
]
print(params)
// This prints ["myString": nil]
在Swift 4.1中更改的原因是ImplicitlyUnwrappedOptional
与Custom(Debug)StringConvertible
的一致性已被删除in this commit,以便在删除类型本身方面取得进展。所以现在使用Swift的默认打印机制(使用反射)打印ImplicitlyUnwrappedOptional
值。
因此,在字典中,您会得到IUO的默认debugDescription
,如下所示:
let aString: String! = "hello"
let params : [String : Any] = [
"myString" : aString
]
print(params)
// This prints ["myString": Swift.ImplicitlyUnwrappedOptional<Swift.String>.some("hello")]
如果你自己打印了它,你会得到它的默认description
,如下所示:
let aString: String! = "hello"
print(aString) // some("hello")
这是因为在Swift 4.1中,ImplicitlyUnwrappedOptional
类型的实现方式与Optional
相同,枚举有两种情况:
public enum ImplicitlyUnwrappedOptional<Wrapped> : ExpressibleByNilLiteral {
// The compiler has special knowledge of the existence of
// `ImplicitlyUnwrappedOptional<Wrapped>`, but always interacts with it using
// the library intrinsics below.
/// The absence of a value. Typically written using the nil literal, `nil`.
case none
/// The presence of a value, stored as `Wrapped`.
case some(Wrapped)
// ...
}
对于具有有效负载值的IUO,因此Swift的默认反射将打印为包含包装值的情况some
。
但这只是暂时的; IUO类型目前(在Swift 4.1中)已被弃用,但它将在Swift 4.2中删除。编译器在很多地方内部使用IUO类型,花了quite a bit of work to remove。因此,在4.2中,您的词典中将包含实际 Optional
值,其值将打印为Optional("hello")
。
答案 1 :(得分:0)
更改此行:
var params : [String : Any] = ["myString" : aString]
为:
var params : [String : String] = ["myString" : aString]
答案 2 :(得分:0)
定义类型
的字典时let dictionary = [String:Any]()
你可以把任何东西放在这本词典中
喜欢
dictionary["name"] = "xyz"
和
dictionary["code"] = 123
在
中let dictionary = [String:String]()
你只能输入一个字符串值
这就是为什么你在访问价值时必须解开价值的原因,因为它可能是任意的
答案 3 :(得分:0)
Any
可以表示任何类型的实例,包括函数类型和可选类型。AnyObject
可以表示任何类类型的实例。你的aString
是一个不应该用于在属性Area中声明的实例对象,如果你将该行放在任何函数/实例function()
中,那么它将完美地工作,因为它将是那么你的实例类型。
总之,你不能在Swift的属性区域中声明实例类型。
override func viewDidLoad() {
let params : [String : Any] = ["myString": aString]
}
即使在物业区,您也不能这样做:
var aString: String! = "String"
var abc = aString
您必须abc = aString
在任何Method()
内完成工作。
希望它会对你有所帮助。