【问题标题】:Is Float, Double, Int an AnyObject?Float、Double、Int 是 AnyObject 吗?
【发布时间】:2015-09-13 20:43:55
【问题描述】:

我阅读了 Swift 的内联文档,我有点困惑。

1) Any 是一个所有类型都隐式遵循的协议。

2) AnyObject 是所有类都隐式遵循的协议。

3) Int, Float, Double 是结构体

这是一个示例代码:

import UIKit

func passAnyObject(param: AnyObject) {
    print(param)
}

class MyClass {}
struct MyStruct {}

let a: Int = 1
let b = 2.0
let c = NSObject()
let d = MyClass()
let e = MyStruct()

passAnyObject(a)
passAnyObject(b)
passAnyObject(c)
passAnyObject(d)
//passAnyObject(e) // Argument type 'MyStruct' does not conform to expected type 'AnyObject'


if a is AnyObject { // b, d, e is also AnyObject
    print("\(a.dynamicType) is AnyObject")
}

我不明白为什么IntDoubleFloatAnyObjects?为什么编译器什么也没说?这些类型被声明为结构。 struct MyStruct 不能传递给顶部的方法,因为它不符合AnyObject

您能帮我理解为什么IntDoubleFloatAnyObject,或者为什么编译器认为它们是?

【问题讨论】:

    标签: ios swift swift2


    【解决方案1】:

    因为您导入了 Foundation,IntDoubleFloat 在传递给采用 AnyObject 的函数时会转换为 NSNumber。类型 String 被转换为 NSString。这样做是为了在调用基于 CocoaCocoa Touch 的接口时更轻松。如果您删除 import UIKit(或 OS X 的 import Cocoa),您将看到:

    error: argument type 'Int' does not conform to expected type 'AnyObject'
    

    当你打电话时

    passAnyObject(a)
    

    这种将值类型隐式转换为对象的方法描述为here.


    Swift 3(Xcode 8 beta 6)更新:

    现在将IntDoubleStringBool 传递给AnyObject 类型的参数会导致错误,例如“Int”类型的参数不符合预期输入“AnyObject”

    在 Swift 3 中,隐式类型转换已被移除。现在需要将IntDoubleStringBoolas AnyObject 一起转换,以便将其传递给AnyObject 类型的参数:

    let a = 1
    passAnyObject(a as AnyObject)
    

    【讨论】:

    • 你是对的。删除了import UIKit,它们现在不符合要求。谢谢!
    • @vacawama:你能解释一下这里的“转换”是什么意思吗?
    • @robo,在这种情况下,编译器会为您创建一个NSNumber 对象。例如,如果您将Int 传递给func test(val: AnyObject),然后在您的函数内部使用if val is NSNumber { print("true") } 进行测试,它确实会打印true,因为Int 变成了NSNumber
    • 这在 Xcode beta 6 中的 Swift 3 中似乎不再适用。有人可以告诉我是什么提案实现了这个功能/错误吗?
    • @shrutim,SE-0072 似乎是罪魁祸首。 github.com/apple/swift-evolution/blob/master/proposals/… 注意:任何 Swift 值也可以使用 as AnyObject 转换为其装箱的 id 表示。
    【解决方案2】:

    好发现! UIKit 实际上将它们转换为NSNumber - @vacawama 也提到过。原因是,有时您正在使用返回或使用 AnyObject 的代码,然后可以将该对象 (as!) 转换为 Int 或其他“结构”。

    【讨论】:

    • 请注意,不建议强制转换。
    • 查看我的答案,为什么编译器在我的情况下没有给出任何错误?我没有导入任何框架。
    【解决方案3】:
    class Test {
    
    static func test() {
        let anyObjectsValues: [AnyObject] = [1, "Two", 3, "Four"] as [AnyObject]
        anyObjectsValues.forEach { (value) in
            switch value {
            case is Int:
                print("\(value) is an Int!")
            case is String:
                print("\(value) is a String!")
            default:
                print("\(value) is some other type!")
            }
        }
    }
    

    }

    我没有导入 UIKit 或 Foundation 框架。为什么编译器没有给出任何错误?甚至打印结果。

    输出:

    1 是一个整数!

    Two 是一个字符串!

    3 是一个整数!

    四是一个字符串!

    有人有想法吗?

    【讨论】:

    • 如果在switch 末尾添加print(type(of: value)),您将看到底层类型仍然基于NSStringNSNumber。 Swift 现在必须包含 Foundation 的部分内容,即使您没有显式导入它。顺便说一句,您的“答案”并不是真正的答案,应该删除并作为新问题发布。
    • 感谢您的回答。我在这里发布它只是因为保持对 AnyObject 的怀疑的相同线程。这样其他开发者也能清楚。
    猜你喜欢
    • 2011-10-11
    • 2013-09-25
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-11
    相关资源
    最近更新 更多