据我所知,Swift对象应符合AnyObject
和Any
,而结构应仅符合Any
。
//Tested with Swift 5.0
class Car {
var name = ""
}
let myArray = [Car]()
let example1 = myArray as? AnyObject
let example2 = myArray as AnyObject
print(example1 != nil) //true
print(example2 != nil) //true
为什么两个例子都是true
?
据我所知example1
应该是nil
,example2
甚至不能编译。
我的误解在哪里?
答案 0 :(得分:3)
由于Objective-C的桥接,您可以在Apple平台上将Array<_>
强制转换为AnyObject
。
Apple平台上的Swift编译器和运行时可以将任何Swift类型转换为某种引用对象。通常,将值类型转换为__SwiftValue
的实例(该实例是NSObject
的子类)。但是,Swift标准库使用一些未记录的语言功能来自定义某些转换:
Array<_>
投射到NSArray
。Dictionary<_, _>
强制转换为NSDictionary
。String
强制转换为NSString
。NSNumber
。答案 1 :(得分:0)
据我所知,
执行此代码后,
let example1 = myArray as? AnyObject
您的myArray
由具有引用计数的实体包装。
作为myArray结构(其他值类型也是如此),它没有引用计数。此时,该值已移至堆。
再次转换为数组时,将从包装器中获取此值对象。
关于文档信息,
https://developer.apple.com/documentation/swift/array
从数组到NSArray的桥接需要O(1)时间和O(1)空间,如果数组的元素已经是一个类或@objc协议的实例;否则,它会占用O(n)的时间和空间。
因此,语句“将数组<_>强制转换为NSArray”实际上是无效的。 对于值类型,它更复杂。
更合适的称呼为“装箱”和“取消装箱”
答案 2 :(得分:-1)
您正在向下转换,编译不会抱怨,因为car类隐式符合AnyObject协议。
与您进行的let example1: AnyObject = myArray as? AnyObject
相同,您可以了解为什么这两个测试为True。