【问题标题】:Swift 2: Why is it necessary to apply ‘as!’ after getting new object by ‘copy()’?Swift 2:为什么必须在通过‘copy()’获取新对象后应用‘as!’?
【发布时间】:2016-08-18 19:55:45
【问题描述】:

我使用 copy() 方法创建了新的 SKEmitterNode 对象。之后我尝试编写emitter.position,但Xcode说“对成员'位置'的模糊引用”。但是,当我使用类型转换«as!在«copy()»之后的SKEmitterNode»,一切正常。请你解释一下,为什么我需要使用«as!»在这种情况下?我无法理解这一点,因为当我在调试器中检查 «emit» 变量的值类型时,我可以看到它已经具有 SKEmitterNode 类型,即使没有使用 «as!在«copy()»之后的SKEmitterNode»。

class GameScene: SKScene, SKPhysicsContactDelegate {

    let bangEmitter : SKEmitterNode = SKEmitterNode(fileNamed: "MyParticle")!

    func makeBang(position: CGPoint) {

        // this method causes an error in second line
        // but, emit is already have type SKEmitterNode, as debugger says
        var emit = bangEmitter.copy()
        emit.position = position

        // this works ok
        var emit = bangEmitter.copy() as! SKEmitterNode
        emit.position = position

    }

}

【问题讨论】:

    标签: swift sprite-kit swift2


    【解决方案1】:

    因为copy() 是由NSObject 定义的方法,并且旨在被子类覆盖以提供自己的实现。 NSObject 本身不支持,调用copy() 会抛出异常。

    由于它是用于子类化的,因此无法确定将返回的对象的类。在 Objective-C 中,它返回一个id;在 Swift 中,这变成了AnyObject。既然你,程序员,知道你从什么类型的对象复制,你可以使用as! SomeClass告诉编译器这个副本是什么类型的对象。

    这也说明了 ObjectiveC 和 Swift 之间的区别。 Objective-C 是动态的。在 Objective-C 中,每次发送消息,运行时都会检查对象是否响应消息。这发生在运行时。在 Swift 中,您调用一个方法,这发生在编译时。编译器必须知道对象的类型才能调用正确的函数/方法。

    这解释了为什么您在调试器中将emit 作为SKEmitterNode 得到 - 这是运行时。编译器在编译时并不知道这一点。

    【讨论】:

      【解决方案2】:

      使用as! 表示检查可能失败。

      Swift 1.2 将保证转换和强制转换的概念分离为两个不同的运算符。保证转换仍使用 as 运算符执行,但强制转换现在使用 as!操作员。这 !表示转换可能会失败。这样,您一眼就知道哪些转换可能导致程序崩溃。

      参考:https://developer.apple.com/swift/blog/?id=23

      【讨论】:

        【解决方案3】:

        查看函数 copy() 的定义,你会发现它总是返回 Any,因此你总是需要将它强制转换为你正在寻找的对象。

        【讨论】:

        • 实际上返回的是AnyObject,而不是Any
        猜你喜欢
        • 1970-01-01
        • 2011-10-02
        • 1970-01-01
        • 2020-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-10
        • 1970-01-01
        相关资源
        最近更新 更多