Swift 中的 AnyObject 和 Any

Posted

技术标签:

【中文标题】Swift 中的 AnyObject 和 Any【英文标题】:AnyObject and Any in Swift 【发布时间】:2014-11-06 16:26:05 【问题描述】:

我不明白在 Swift 中何时使用 AnyObject 以及何时使用 Any

就我而言,我有一个Dictionary

[字符串:???]

??? : 可以是Int, Double, Float, String, Array, Dictionary

谁能解释一下AnyAnyObject之间的区别 以及在我的情况下使用哪一个。

【问题讨论】:

【参考方案1】:

您使用Any 还是AnyObject 取决于您的预期用途:

如果您的字典仅在 Swift 代码中使用,那么您应该使用 Any,因为您的类型(IntDoubleFloatStringArrayDictionary)不是对象。

如果您要将字典传递给期望 NSDictionary 的 Objective-C 例程,那么您应该使用 AnyObject

当您 import Foundationimport UIKitimport Cocoa 时,可以将您的数组声明为 [String: AnyObject],但在这种情况下,Swift 会将您的 IntDoubleFloat 文字视为NSNumber,您的Strings 为NSString,您的Arrays 为NSArray,您的字典为NSDictionary,所有这些都是对象。使用AnyObject 作为值类型的字典可以转换为NSDictionary,但使用Any 的字典则不能。

【讨论】:

【参考方案2】:

AnyObject 仅用于引用类型(类),Any 用于值和引用类型。

所以你应该去[String: Any]

Any 和 AnyObject 的类型转换

Swift 提供了两种特殊类型来处理非特定类型:

Any 可以表示任何类型的实例,包括函数 类型。 AnyObject 可以表示任何类类型的实例。

注意:

仅当您明确需要该行为和 他们提供的能力。最好具体一点 您希望在代码中使用的类型。

来自 Swift 编程语言: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html#//apple_ref/doc/uid/TP40014097-CH22-ID342

-

还请注意,当您使用 Cocoa API 时,通常会收到一个 AnyObject 数组,这是因为 Objective-C 数组不是典型的。 所以你需要将它们转换为你期望的数组类型。

-

编辑:(2015 年 12 月 22 日) 在最后一条语句中,请注意这在 Swift 2.0 和 Xcode 7 中发生了变化。 Apple 在 Objective-C 中引入了‘Lightweight’ generics,因此许多 Cocoa API 现在已经返回正确的类型。

编辑:(2016 年 10 月 18 日) 请注意,从 Swift 3.0 开始,Objective-C ids 现在被导入为 Any,而不是 AnyObject

【讨论】:

请注意,StringArrayDictionary 不是类,对于这些使用 Any。 Nor Int、Double 和 Float 都是。 是的,但这通常是显而易见的。 NSStringNSArrayNSDictionary 是类并不是很明显,但功能相似的 Swift 版本不是类,这让许多开发人员感到困惑。 Any 是否也代表选项?还是应该表示为 Any? @robdashnash Any 不代表可选项。 ?应添加以使其成为可选【参考方案3】:

Check this SO answer:

泛型是类型安全的,这意味着如果您将字符串作为泛型传递并尝试将其用作整数,编译器会报错并且您将无法编译您的(这很好)。 (发生这种情况是因为 Swift 使用的是静态类型,并且能够给你一个编译器错误)。 如果你使用 AnyObject,编译器不知道这个对象是可以被视为字符串还是整数,并且基本上允许你对它做任何你想做的事情(这很糟糕),就好像你尝试使用一个已经被当它是一个整数时作为字符串传递,应用程序将崩溃。 (这是因为 Swift 使用的是动态类型,只会给你一个运行时错误)

【讨论】:

【参考方案4】:

根据 Apple 的 Swift 文档,

Any 可以表示任何类型的实例,包括函数 类型和可选类型。 AnyObject 可以表示任何类类型的实例。

更多详情请查看:Blog

【讨论】:

【参考方案5】:

默认情况下,我们应该使用“Any”,如果我们需要更高的精度,那么我们可以选择更多受约束的类型,例如 AnyHashable、AnyObject、AnyClass、CustomType 等。

在将对象打磨到用 Objective-C 编写的框架(如 UIKit 和 Foundation)时,应使用 AnyObject。

AnyObject 接受类类型的实例,但不接受枚举、结构和可选类类型对象的实例:

class CustomType 
   var instanceArg1: Int
   var instanceArg2: String
   static var classArg1: Int

AnyObject 类型的特殊性在于该类型的对象可以通过自动完成访问所有@objc 方法和变量。如果导入 UIKit 或 Foundation,则 AnyObject 实例对象可以通过自动完成访问所有 Foundation 对象的所有变量和方法。

下面的代码首先在运行时编译但应用程序崩溃,因为给定的参数是 String 类型而不是 UITableView 并且没有在 String 类型中定义的方法 tableView(_:numberOfRowsInSection)。

import UIKit

class CustomType 

    func customMethod(arg1: AnyObject) 
        let tableView = UITableView()
        let numberOfRows = arg1.tableView(tableView, numberOfRowsInSection: 0)
    

【讨论】:

以上是关于Swift 中的 AnyObject 和 Any的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中的错误:(键:AnyObject,值:AnyObject)' 不能转换为 'NSDictionary'

swift中Any,AnyObject,AnyClass的区别

为啥在 Swift 中的铸造成本如此之高,而不是……将其保留为 AnyObject?

将“var touch:AnyObject?= touches.anyObject()”转换为 Swift 1.2 [重复]

如何在 Swift 中将键值对添加到类型为 [String:AnyObject] 的字典中?

Swift [1,2] 符合 AnyObject 但 [Enum.a, Enum.b] 不符合