AnyObject 可以代表任何 class 类型的实例
Any 可以表示任意类型,甚至包括方法 (func) 类型
如果我们注意到 AnyObject 的定义,可以发现它其实就是一个接口
protocol AnyObject {
}
特别之处在于,所有的 class 都隐式地实现了这个接口,这也是 AnyObject 只适用于 class 类型的原因。而在 Swift 中所有的基本类型,包括 Array 和 Dictionary 这些传统 意义上会是 class 的东西,统统都是 struct 类型,并不能由 AnyObject 来表示,于是 Apple 提出了一个更为特殊的 Any,除了 class 以外,它还可以表示包括 struct 和 enum 在内的所有类型。
我们在这里声明了一个 Int 和一个 String,按理说它们都应该只能被 Any 代表,而不 能被 AnyObject 代表的
其实说真的,使用 Any 和 AnyObject 并不是什么令人愉悦的事情,正如开头所说,这都 是为妥协而存在的。如果在我们自己的代码里需要大量经常地使用这两者的话,往往 意味着代码可能在结构和设计上存在问题,应该及时重新审视。简单来说,我们最好 避免依赖和使用两者,而去尝试明确地指出确定的类型.
接下来看下二者的定义
// 所有类型隐含一致遵循的协议
public typealias Any = protocol<>
//所有类都默认遵循的协议
@objc public protocol AnyObject {
}
从以上可以看出Any和AnyObject都是协议而且,并且从Apple提供的注释中可以看出所有的类型都隱式实现了Any协议,所有的class都隱式实现了AnyObject协议。
总结:
AnyObject是Any的子集
所有用class关键字定义的对象就是AnyObject
所有不是用class关键字定义的对象就不是AnyObject,而是Any
下面来举例说明:
1.Any – 比如我们经常使用的参数parameters
parameters = [“appId”:”123456”, “timestamp”:203428394820,
“version”:”1.0”, “appAuthToken”:”7D8SF7D8VS8987D67687”,
“bizContent”:[“pageStart”:1, “pageSize”: “10”,”isTrue”:true]] as [String : Any]
这里面包括了String,Int,Bool,Dictionnary四种类型的参数,最后使用as [String : Any] ,就是说,parameters的key是String类型,但是value值可以是任何类型。
2.AnyObject – 在做网络请求的时候
typealias Complicate = (AnyObject) ->Void
//请求回调
var complicate : Complicate?
func request(type:RequestType, URLString:String, parameters:[String : AnyObject], complicate:@escaping Complicate) -> Void {
switch type {
case .requestTypeGet:
Alamofire.request(URLString, method: .get, parameters: parameters, encoding: JSONEncoding.default, headers: nil)
.validate()
.responseJSON { response in
switch response.result{
case .success:
if let value = response.result.value{
//把得到的JSON数据转为字典
complicate(value as AnyObject)
}
case .failure: () DMCAlertCenter.default().postAlert(withMessage: "网络请求失败")
return
}
}
可以看到,在返回的json进行回调的时候,由于value是JSON类型的实例,complicate(value as AnyObject), 就是将value作为AnyObject传值出去。
Any:
Any是一个空协议集合的别名,它表示没有实现任何协议,因此它可以是任何类型,包括类实例与结构体实例。
Any是一个别名。
/// 一个任何类型都遵守的协议类型
typealias Any = protocol<>
AnyObject:
AnyObject是一个成员为空的协议,任何对象都实现了这个协议。
看一下AnyObject的定义:
@objc protocol AnyObject {
}
AnyClass:
AnyClass是AnyObject.Type的别名而已。
看一下AnyClass的定义:
typealias AnyClass = AnyObject.Type
@objc是一个声明特性,该特性用于修饰任意可以在ObjC中访问或使用的声明,比如非嵌套类,协议,类和协议中的属性和方法,初始化器,析构器,以及下标。如果你将objc特性应用于一个类或协议,它也会隐式地应用于那个类或协议的成员。对于标记了objc特性的类,编译器会隐式地为它的子类添加objc特性
AnyObject使用@objc声明特性修饰,是因为它要做为Objc与Swift混编的使者,两者传递变量很多类型便是AnyObjct。
不同于Any,AnyObject是一个没有声明任何成员的空协议,是Any表示一个空的协议集合。
总结:
AnyObject是一个协议,Any是零个协议!
AnyObject用于任何类实例,而Any用于任何变量。
看一下AnyObject的定义:
@objc protocol AnyObject {
}
看一下AnyClass的定义:
typealias AnyClass = AnyObject.Type
AnyClass-它确实仅是一个别名而已。Any也是别名,是protocol<>的别名。
@objc
在 Swift 代码中,使用@objc修饰后的类型,可以直接供 Objective-C 调用。可以使用@objc修饰的类型包括:
未嵌套的类
协议
非泛型枚举(仅限于原始值为整形的类型)
类和协议中的属性和方法
构造器和析构器
下标
类
@objc class MyHelper:NSObject {
// class code
}
Objective-C 中所有的类都需要继承自NSObject,Swift 中的类需要供 Objective-C 调用的时候,自然也需要继承自NSObject(谢谢网友潇小溅纠错:Swift 中声明继承NSObject 的类,不需要显式使用 @objc 修饰, Swift 编译器会默认加上)。当然,你也可以继承所有 Objective-C 中的类,因为他们本身也继承自NSObject:
@objc class MyViewController : UIViewController {
}
协议
@objc修饰协议与修饰类一样,需要注意的是,如果协议中有optional修饰的方法,就必须使用@objc来修饰:
@objc protocol CounterDataSource {
optional func incrementForCount(count: Int) -> Int
optional var fixedIncrement: Int { get }
}
枚举
Swift 中的枚举类型,功能增强了不少。Objective-C 中还是传统的枚举类型,必须使用整型作为原始值。这样看来,Swift 中的枚举类型如果要被@objc修饰,则需要满足原始值是整型的限制条件。不然就会报编译错误。
关于如何在 Objective-C 中使用 Swift 枚举类型
// Swift
@objc enum Bear: Int {
case Black, Grizzly, Polar
}
// OC
Bear type = BearBlack;
switch (type) {
case BearBlack:
case BearGrizzly:
case BearPolar:
[self runLikeHell];
}
其他
在类和协议中的属性和方法,构造器和析构器,下标中使用@objc修饰的用法与上面的用法一样
@objc class ExampleClass: NSObject {
var enabled: Bool {
@objc(isEnabled) get {
// Return the appropriate value
}
}
}
需要注意的是,如果类中方法或者属性被@objc修饰,那么类就必须被@objc修饰。