swift中any,anyobject,anyclass的区别

6度XZ 6度XZ     2022-09-16     714

关键词:

这几个概念让人很迷惑,看了很多帖子,终于搞明白了,简单总结:

Any 和 AnyObject 是 Swift 中两个妥协的产物。什么意思呢,oc中有个id关键字,表示任何对象,oc和swift混编的时候拿什么对应id呢?就发明出来了AnyObject。但是!oc中的NSString,NSArray等都是class,但是在swift中String,Array都是struct,这个怎么办呢,混编的时候NSString等类型对应的id就不能用AnyObject了,为了填坑,又搞出来个Any,表示任意类型。看看官方文档的定义:

AnyObject 可以代表任何 class 类型的实例
Any 可以表示任意类型,甚至包括方法 (func) 类型

而AnyClass只是AnyObject的别名。和AnyObject一样。

先来说说 AnyObject 吧。写过 Objective-C 的读者可能会知道在 Objective-C 中有一个叫做 id 的神奇的东西。编译器不会对向声明为 id 的变量进行类型检查,它可以表示任意类的实例这样的概念。在 Cocoa 框架中很多地方都使用了 id 来进行像参数传递和方法返回这样的工作,这是 Objective-C 动态特性的一种表现。现在的 Swift 最主要的用途依然是使用 Cocoa 框架进行 app 开发,因此为了与 Cocoa 架构协作,将原来 id 的概念使用了一个类似的,可以代表任意 class 类型的 AnyObject 来进行替代。

但是两者其实是有本质区别的。在 Swift 中编译器不仅不会对 AnyObject 实例的方法调用做出检查,甚至对于 AnyObject 的所有方法调用都会返回 Optional 的结果。这虽然是符合 Objective-C 中的理念的,但是在 Swift 环境下使用起来就非常麻烦,也很危险。应该选择的做法是在使用时先确定 AnyObject 真正的类型并进行转换以后再进行调用。

假设原来的某个 API 返回的是一个 id,那么在 Swift 中现在就将被映射为 AnyObject? (因为 id 是可以指向 nil 的,所以在这里我们需要一个 Optional 的版本),虽然我们知道调用来说应该是没问题的,但是我们依然最好这样写:

func someMethod() -> AnyObject? {
    // ...

    // 返回一个 AnyObject?,等价于在 Objective-C 中返回一个 id
    return result
}

let anyObject: AnyObject? = SomeClass.someMethod()
if let someInstance = anyObject as? SomeRealClass {
    // ...
    // 这里我们拿到了具体 SomeRealClass 的实例

    someInstance.funcOfSomeRealClass()
}

如果我们注意到 AnyObject 的定义,可以发现它其实就是一个接口:

protocol AnyObject {
}

特别之处在于,所有的 class 都隐式地实现了这个接口,这也是 AnyObject 只适用于 class 类型的原因。而在 Swift 中所有的基本类型,包括 Array 和 Dictionary 这些传统意义上会是 class的东西,统统都是 struct 类型,并不能由 AnyObject 来表示,于是 Apple 提出了一个更为特殊的 Any,除了 class 以外,它还可以表示包括 struct 和 enum 在内的所有类型。

为了深入理解,举个很有意思的例子。为了实验 Any 和 AnyObject 的特性,在 Playground 里写如下代码:

import UIKit

let swiftInt: Int = 1
let swiftString: String = "miao"

var array: [AnyObject] = []
array.append(swiftInt)
array.append(swiftString)

我们在这里声明了一个 Int 和一个 String,按理说它们都应该只能被 Any 代表,而不能被 AnyObject 代表的。但是你会发现这段代码是可以编译运行通过的。那是不是说其实 Apple 的编程指南出错了呢?不是这样的,你可以打印一下 array,就会发现里面的元素其实已经变成了 NSNumber 和 NSString 了,这里发生了一个自动的转换。因为我们 import 了 UIKit (其实这里我们需要的只是 Foundation,而在导入 UIKit 的时候也会同时将 Foundation 导入),在 Swift 和 Cocoa 中的这几个对应的类型是可以进行自动转换的。因为我们显式地声明了需要 AnyObject,编译器认为我们需要的的是 Cocoa 类型而非原生类型,而帮我们进行了自动的转换。

在上面的代码中如果我们把 import UIKit 去掉的话,就会得到无法适配 AnyObject 的编译错误了。我们需要做的是将声明 array 时的 [AnyObject] 换成 [Any],就一切正确了。

let swiftInt: Int = 1
let swiftString: String = "miao"

var array: [Any] = []
array.append(swiftInt)
array.append(swiftString)
array

顺便值得一提的是,只使用 Swift 类型而不转为 Cocoa 类型,对性能的提升是有所帮助的,所以我们应该尽可能地使用原生的类型。

其实说真的,使用 Any 和 AnyObject 并不是什么令人愉悦的事情,正如开头所说,这都是为妥协而存在的。如果在我们自己的代码里需要大量经常地使用这两者的话,往往意味着代码可能在结构和设计上存在问题,应该及时重新审视。简单来说,我们最好避免依赖和使用这两者,而去尝试明确地指出确定的类型。

转载自:ANY 和 ANYOBJECT

swift开发第九篇——any和anyobject&typealias和泛型接口

本篇分为两部分:一、Swift中的Any和AnyObject二、Swift中的typealias和泛型接口  一、Swift中的Any和AnyObject  在Swift中,AnyObject可以代表任何class类型的实例,Any可以表示任意类型,包括方法(func)类型,相当于OC中的id。因为id可以... 查看详情

适配swift3

AnyvsAnyObject将项目里的AnyObject转成Any可能是大家遇到的第一件适配大事。如何解释这个变化呢?在Swift3之前,我们可以写完一个项目都只用AnyObject来代表大多数实例,好像不用与Any类型打交道。但事实上,Any和AnyObject是有明显区... 查看详情

NSFastEnumerationIterator.Element(又名 Any)不符合协议“AnyObject”

】NSFastEnumerationIterator.Element(又名Any)不符合协议“AnyObject”【英文标题】:NSFastEnumerationIterator.Element(akaAny)doesnotconformtoprotocol\'AnyObject\'【发布时间】:2016-09-0722:58:48【问题描述】:升级到Xcode8(Swift3)后,当我尝试在快照中单步... 查看详情

类型“NSFastEnumerationIterator.Element”(又名“Any”)不符合协议“AnyObject”

...NSFastEnumerationIterator.Element”(又名“Any”)不符合协议“AnyObject”【英文标题】:Type\'NSFastEnumerationIterator.Element\'(aka\'Any\')doesnotconformtoprotocol\'AnyObject\'【发布时间】:2016-10-3000:37:16【问题描述】:我正在尝试将我的应用程序更新... 查看详情

Dictionary<AnyHashable: Any> 在 Swift 3 中 Any 可能持有 nil 值

...以解释为什么这在Swift3中有效吗?vardict:[AnyHashable:Any]letb:AnyObject?=n 查看详情

类型 Any 没有下标成员 Swift 3.0

...】:尝试转换函数以使其与Swift3.0兼容。必须将参数json从AnyObject更改为Any:fileprivatefunccheckForAuthorizationFailure(_json:Any)->BoolletresponseMess 查看详情

anyanyobjectas

...种类型别名Any:可表示随意类型,(Int、Double等值类型)。AnyObject:可表示随意class类型实例,一个不论什么对象类型的数组Any类型:classCalculate{varNumberA:Any!varNumberB:Any!init(Numbera:Any,Numberb:Any){self.NumberA=Numberaself.NumberB=Numb 查看详情

Xcode 8 beta 6 AnyObject Swift 3 变化

】Xcode8beta6AnyObjectSwift3变化【英文标题】:Xcode8beta6AnyObjectSwift3changes【发布时间】:2016-08-1813:53:29【问题描述】:Xcodebeta6改变了一些Swift语言由于“id”现在导入为“Any”而不是“AnyObject”,您可能会在之前对“AnyObject”执行动... 查看详情

为啥布尔“AnyObject”而不是“Any”?

】为啥布尔“AnyObject”而不是“Any”?【英文标题】:WhyisBool"AnyObject"insteadof"Any"?为什么布尔“AnyObject”而不是“Any”?【发布时间】:2016-06-0815:21:53【问题描述】:我有一个简单的问题:为什么Bool符合AnyObject根... 查看详情

在 Swift 2 中过滤 AnyObject

】在Swift2中过滤AnyObject【英文标题】:FilterAnyObjectinSwift2【发布时间】:2016-02-0206:29:07【问题描述】:我有一个名为data的JsonArray,我将其传递给AnyObject:ifletdtMenu:AnyObject=responseObject?.valueForKey("data")print(filteredMenu)//我在这里得到了... 查看详情

类型'(String,AnyObject)'在swift中没有下标成员

】类型\\\'(String,AnyObject)\\\'在swift中没有下标成员【英文标题】:Type\'(String,AnyObject)\'hasnosubscriptmembersinswift类型\'(String,AnyObject)\'在swift中没有下标成员【发布时间】:2016-11-1012:22:01【问题描述】:我正在使用这条线来获... 查看详情

上下文类型 'Any' 不能与数组文字 Swift 3 一起使用

...转换为Swift3,但我无法转换以下代码。当我使用Any而不是AnyObject时,我收到如下 查看详情

NsMutable 不是 swift 中 [anyobject] 的子类型

】NsMutable不是swift中[anyobject]的子类型【英文标题】:NsMutableisnotsubtypeof[anyobject]inswift【发布时间】:2015-03-0408:07:47【问题描述】:我想从NSUserdefault获取数组并将其存储到NsMutableArray但不幸的是它失败了。错误NsMutableisnotsubtypeof[any... 查看详情

无法将“Swift.UInt64”(0x10dddde88)类型的值转换为“Swift.AnyObject”(0x12129d018)

...无法将“Swift.UInt64”(0x10dddde88)类型的值转换为“Swift.AnyObject”(0x12129d018)【英文标题】:Couldnotcastvalueoftype\'Swift.UInt64\'(0x10dddde88)to\'Swift.AnyObject\'(0x12129d018)【发布时间】:2016-12-1506:35:51【问题描述】:在Swift2.3中,我必须将U... 查看详情

在 Swift 中使用 JSON 的 Alamofire 请求后,如何在 AnyObject 中转换 <AnyObject> 响应?

】在Swift中使用JSON的Alamofire请求后,如何在AnyObject中转换<AnyObject>响应?【英文标题】:Howtoconvert<AnyObject>responseinAnyObjectafteranAlamofirerequestwithJSONinSwift?【发布时间】:2015-09-1810:06:51【问题描述】:所以我想向应该返回JSON... 查看详情

在 Swift 中,对于 AnyObject,我如何 setValue() 然后调用 valueForKey()

】在Swift中,对于AnyObject,我如何setValue()然后调用valueForKey()【英文标题】:InSwift,forAnyObject,howdoIsetValue()thencallvalueForKey()【发布时间】:2014-10-3104:06:36【问题描述】:我想在AnyObject中存储一个值,然后按如下方式检索它:varobj:Any... 查看详情

如何在 swift 中使用 AnyObject 将结构转换为对象

】如何在swift中使用AnyObject将结构转换为对象【英文标题】:HowastructisgettingconvertedasanobjectusingAnyObjectinswift【发布时间】:2016-05-0509:39:49【问题描述】:在以下示例中,testString被声明为String的对象,该对象是一个结构。但是我们... 查看详情

在 Swift 中:Array VS NSArray VS [AnyObject] 之间的区别

】在Swift中:ArrayVSNSArrayVS[AnyObject]之间的区别【英文标题】:inSwift:DifferencebetweenArrayVSNSArrayVS[AnyObject]【发布时间】:2015-05-0712:31:43【问题描述】:正如标题所说,ArrayvsNSArrayvs[AnyObject]有什么区别?此外,最推荐的解决方法是什么... 查看详情