swift - 转换为 typeof(self)

标签 swift

是否有可能创建一个类别(扩展),最终返回一个转换为 instancetype 的对象?我有一个加载 SKS 文件的类别,但由于此类别用于 SKNode,因此所有其他子类(如 SKSceneSKEmitterNode 等)将采用也是。

所以我只想避免总是从 SKNode 转换为 instancetype。是否可以将返回类型更改为 instancetype 并确保编译器对返回值满意?

我想我可以使用 -> Self 作为返回类型,但是我不知道如何将 scene 转换为 instancetype 这样这个东西就可以编译了..

例如:

SKEmitterNode.unarchiveFromFile("Blah") 会返回一个 SKEmitterNode

的实例
extension SKNode {
    class func unarchiveFromFile(file: String) -> SKNode {
        let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks")
        var sceneData = NSData.dataWithContentsOfFile(path, options: .DataReadingMappedIfSafe, error: nil)

        let unarchiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
        unarchiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")

        let scene = unarchiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as SKNode
        unarchiver.finishDecoding()

        return scene
    }
}

最佳答案

这可能对您有用。我无法测试它,因为我没有太多经验 SpriteKit 。但它确实编译并且编译器推断类型为

let e = SKEmitterNode.unarchiveFromFile("Blah")

是 SKEmitterNode。这个想法是定义一个通用的辅助函数

func unarchiveFromFileHelper<T where T : SKNode>(file: String) -> T 

这样

class func unarchiveFromFile(file: String) -> Self {
    // define helper function ...
    return unarchiveFromFileHelper(file)
}

使用 T == Self 调用辅助函数。

extension SKNode {
    class func unarchiveFromFile(file: String) -> Self {

        func unarchiveFromFileHelper<T where T : SKNode>(file: String) -> T {
            let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks")
            var sceneData = NSData.dataWithContentsOfFile(path, options: .DataReadingMappedIfSafe, error: nil)

            let unarchiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
            unarchiver.setClass(T.classForKeyedUnarchiver(), forClassName: "SKScene")

            let scene = unarchiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as T
            unarchiver.finishDecoding()
            return scene
        }

        return unarchiveFromFileHelper(file)
    }
}

更新:如果您的目标是 iOS 8/OS X 10.10 或更高版本,那么 不再需要自定义解档方法。正如在 Cannot use unarchiveFromFile to set GameScene in SpriteKit , 你可以使用

convenience init?(fileNamed filename: String)

来自 SKNode 父类(super class),例如

if let e = SKEmitterNode(fileNamed: "Blah") {
    // ...
}

关于swift - 转换为 typeof(self),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25271208/

相关文章:

ios - 点击 Sprite 时发生的其他 Action ;如何预防

ios - 如何在 Swift 4 中的 View Controller 中将多个 uiview 拖动到另一个 uiview 或图像上

ios - 外包 TableView 协议(protocol)

swift - 如何在 Xcode 中左对齐导航栏的标题?

ios - 展开 segue 不展开

ios - 从顶部收缩 UIView

swift - 如何使用 Carthage 分发可设计/可检查的自定义 View

Swift:扩展 print() 函数的功能

swift - 查找两个字符串范围之间或字符串末尾的字符串

ios - 如何编译 `.framework`文件?