转换为typeof(self)

时间:2014-08-12 18:08:30

标签: 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
    }
}

1 个答案:

答案 0 :(得分:21)

这可能适合你。我无法测试它,因为我没有多少经验 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超类的

,例如

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