Swift SpriteKit使用struct而不是class来呈现精灵

时间:2016-03-03 13:53:13

标签: swift struct skspritenode

我最近一直在更新我的游戏以使用更多的值类型。在某些情况下,我仍然没有100%的自信,因为我采用了结构方式以避免强大的参考周期。根据苹果更新的主题演讲,似乎价值类型无论如何都是他们的方式。

我从未见过在spriteKit游戏中使用结构体来渲染精灵的例子,所以我想知道它们有什么缺点。 我知道它们被复制而没有被引用,但是对于我的使用它似乎有效。

所以基本上在做这个时我需要注意的事情

struct Flag {
   let post: SKSpriteNode
   let flag: SKSpriteNode

  init(postImage: String, flagImage: String) {
     post = SKSpriteNode(imageNamed: postImage)
     // other set ups for post sprite

     flag = SKSpriteNode(imageNamed: flagImage)
     // other set ups for flag sprite
     post.addChild(flag)
   }

   func animate() {
       // code to animate flag
   }
}

在我的SKScenes中,我只是像往常一样添加它们

 let flag = Flag(postImage: "FlagPostImage", flagImage: "FlagImage")
 flag.post.position = ...
 addChild(flag.post)
 flag.animate()

现在,即使我在同一个场景中创建多个标志,我似乎也没有遇到任何问题。 我只是很好奇,因为我从来没有真正看过这样的例子,所以我想知道我是否遗漏了某些东西,比如性能缺陷等。

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

我个人避免创建包含Classes的{​​{1}}。由于Structs副本,在您的应用中传递的每个副本都会增加Classes的引用次数。这使得管理它们变得更加困难而不是更容易。

了解UIKit如何使用Structs也很有用。 UIView是一个对象,但有许多定义属性Structs。例如,它是frame

将以下代码放在操场上以查看此行为的一些影响。 protocol只是为了从操场上获得一些有意义的反馈。

protocol IDLookable : CustomPlaygroundQuickLookable {

    var id : Int { get set }

}

extension IDLookable {

    func customPlaygroundQuickLook() -> PlaygroundQuickLook {
        return PlaygroundQuickLook.AttributedString(NSAttributedString(string: "\(self.dynamicType) with id : \(self.id)"))
    }
}


class MyClass : IDLookable {

    var id : Int = 0

    init(id : Int) {
        self.id = id
    }
}

struct MyContainerStruct : IDLookable {

    var id : Int = 0
    var object : MyClass

    init(id : Int, object:MyClass) {
        self.id = id
        self.object = object
    }
}

class Scope {

    // ref count = 1
    var object = MyClass(id: 11)
    var structContainer : MyContainerStruct

    init() {
        // ref count = 2
        structContainer = MyContainerStruct(id: 222, object: object)
        messWithAClassInAStruct()
    }

    func messWithAClassInAStruct() {

        // ref count = 3
        var structContainerTwo = structContainer
        structContainerTwo.id = 333
        structContainerTwo.object // 11

        // altering the object in one struct will obvously update all references
        structContainerTwo.object.id = 1
        structContainer.object // 1
        structContainerTwo.object // 1

    }
}

let test = Scope()

Reference Types中使用Value Types可以轻松使用的一种模式是将它们weak optionals存储在Value Types中。这意味着某些内容需要strong reference,但有些Class可能会负责创建Structs这是保留strong reference的好地方。< / p>

struct MyContainerStruct : IDLookable {

    var id : Int = 0
    weak var object : MyClass?

    init(id : Int, object:MyClass) {
        self.id = id
        self.object = object
    }
}

class Scope {

    // ref count = 1
    var object = MyClass(id: 11)
    var structContainer : MyContainerStruct

    init() {
        // ref count = 1
        structContainer = MyContainerStruct(id: 222, object: object)
        messWithAClassInAStruct()
    }

    func messWithAClassInAStruct() {
        // ref count = 1
        var structContainerTwo = structContainer
        structContainerTwo.id = 333
        structContainerTwo.object // 11
    }
}

let test = Scope()