【问题标题】:Whats the correct way, using "init" or "didmove"?使用“init”或“didmove”的正确方法是什么?
【发布时间】:2016-11-28 18:12:25
【问题描述】:

语言:Swift 3.0 --- IDE:Xcode 8.0 beta 2 --- 项目:iOS 游戏 (SpriteKit)

我为 iOS 创建了一个游戏,我知道 Apple 非常严格地接受应用程序/游戏的规则。所以我想知道设置游戏的正确方法是什么。

我从 google 学习创建一个新的 SpriteKit 项目并进行以下设置:

GameViewController.swift 中清除 viewDidLoad() 并添加所有内容:

override func viewDidLoad() {
    super.viewDidLoad()
    let skView = self.view as! SKView

    let scene = GameScene(size: skView.bounds.size)
    scene.scaleMode = .aspectFit

    skView.presentScene(scene)
}

GameScene.swift 中删除所有内容并保留此代码:

import SpriteKit

class GameScene: SKScene {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(size: CGSize) {
        super.init(size: size)
        // add all the code of the game here...
    }

}

并在 override init 中开发我的游戏

但我认为用 init 开始游戏实际上是错误的。而正确的方法是使用 didMove() 方法。那么代码应该写在里面吗? :

override func didMove(to view: SKView) {
    <#code#>
}

有谁知道哪个是正确的方法?为什么?另外,如果我这样做的方式不对,你能解释一下如何使用 didMove 方法吗?

不知道这是不是一个愚蠢的问题,只是困扰我使用 init 是错误的,并想问是否有人对此了解更多。

【问题讨论】:

  • 我不推荐这个 -> let scene = GameScene(size: skView.bounds.size),使用 GameScene(fileNamed:)GameScene()scaleMode = .ResizeFillGameScene(size:) 应该与其他 3 个 scaleModes、.Fill.AspectFill.AspectFit 一起使用,仅当您希望场景在所有设备上具有静态大小时。使用您使用的方式是否会伤害,只有当您动态更改视图大小时,但是如果您可以自己编程以在创建错误之前停止错误,那么这就是进步。
  • 没有正确或错误的方式,但您介绍的方式是我创建游戏的方式,因为我使用 .AspectFill 并将大小设置为 iPad 的分辨率。此外,init 是初始化类变量/初始化类具有的值(防止值为零)。当视图呈现给用户时调用 didMoveToView。

标签: ios objective-c swift sprite-kit swift3


【解决方案1】:

覆盖 SKScene 初始化

你可以像@Knight0fDragon 描述的那样覆盖SKScene 的初始化器

class GameScene : SKScene {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()             
    }

    override init() {
        super.init()
        setup()
    }

    override init(size: CGSize) {
        super.init(size: size)
        setup()
    }

    func setup()
    {
        // PUT YOUR CODE HERE

    }
}

或者你可以使用 didMove(to:)

class GameScene: SKScene {
    override func didMove(to view: SKView) {
        super.didMove(to: view)
        // PUT YOUR CODE HERE <-----
    }
}

init 仅在场景初始化时被调用。 didMove 在场景呈现到视图中时被调用。

【讨论】:

  • 所以我只是复制粘贴了在 didMove 中的 init 上的相同代码? didMove 是否像 init 一样运行 1 次并设置游戏并结束?
  • 重写SKScene init并没有错,其实就是想用这个来设置场景的初始状态。在您使用 coder 调用 init 之后,孩子们也在场。这使您可以在甚至需要转换之前很久就初始化和准备场景。 (加载屏幕上的时间更少,耶)。使用didMove(to:view) 实际上不是一个好地方,因为如果你设计一个使用多个场景的游戏,那么每次转换发生时都会触发它,迫使你添加一个 if 块来进行检查。
  • @Knight0fDragon: yes you can, in order to get access to convenience methods, you need to override all designated inits 好的,但我说的是If you override the init(s) like in the example you won't be able to call GameScene(fileNamed:"GameScene")。顺便说一句,您能否为 GameScene 提供 init?(fileNamed: String) 的工作覆盖版本?我想进行一些测试。
  • @pRivaT3BuG,那是因为您使用的是 GameScene(size:) 将您的代码放在那里(我已经评论过您不应该使用它)
  • 或者,让你的生活更轻松,创建一个新的 setup 方法,并让所有 3 个 init 调用 setup 方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-09
  • 2017-01-07
  • 1970-01-01
  • 2021-11-24
  • 2021-09-23
  • 2017-04-07
  • 2013-01-09
相关资源
最近更新 更多