Как правильно использовать init или didmove?

Язык: Swift 3.0 --- IDE: Xcode 8.0 beta 2 --- Проект: iOS Game (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 неправильно, и я хотел спросить, знает ли кто-нибудь об этом больше.


person pRivaT3 BuG    schedule 25.07.2016    source источник
comment
Я бы не рекомендовал это -› let scene = GameScene(size: skView.bounds.size), используйте GameScene(fileNamed:) или GameScene() с scaleMode = .ResizeFill. GameScene(size:) следует использовать с другими тремя режимами масштабирования, .Fill, .AspectFill и .AspectFit, только если вы хотите, чтобы сцена имела статический размер на всех устройствах. Больно ли использовать то, как вы используете, только когда у вас динамически изменяется размер представления, но эй, если вы можете запрограммировать себя, чтобы остановить ошибки до того, как они будут созданы, тогда это прогресс.   -  person Knight0fDragon    schedule 25.07.2016
comment
Нет правильного или неправильного способа, но именно так, как вы представили, я создаю свои игры, поскольку я использую .AspectFill и делаю размер разрешением iPad. Кроме того, init предназначен для инициализации переменных класса/инициализации значений, которые имеет класс (предотвращает нулевые значения). didMoveToView вызывается, когда представление было представлено пользователю.   -  person Jose Ramirez    schedule 26.07.2016


Ответы (1)


Переопределение инициализации SKScene

Вы можете переопределить инициализаторы SKScene, как описано @Knight0fDragon.

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 вызывается, когда сцена представлена ​​в представлении.

person Luca Angeletti    schedule 25.07.2016
comment
Итак, я просто копирую и вставляю тот же код, что и при инициализации, внутри didMove? А didMove запускается 1 раз и настраивает игру и завершается, как и init? - person pRivaT3 BuG; 25.07.2016
comment
@pRivaT3BuG: didMove происходит, когда сцена представлена ​​в формате SKView. Он выполняется только один раз (если вы не удалите его из представления и не добавите снова, но это довольно редко). Однако это подходящее место для настройки вашей сцены. Это похоже на то, когда в приложении UIKit вы настраиваете свой ViewController внутри viewDidLoad. - person Luca Angeletti; 25.07.2016
comment
Нет ничего плохого в переопределении инициализации SKScene, на самом деле вы хотите использовать это для настройки начального состояния сцены. Дети также присутствуют после того, как вы вызовете init с кодером. Это позволяет инициализировать и подготовить сцену задолго до того, как потребуется переход. (Меньше времени на экране загрузки, YAY). Использование didMove(to:view) на самом деле не лучшее место, потому что если вы разрабатываете игру, в которой используется несколько сцен, то это будет запускаться каждый раз, когда происходит переход, заставляя вас добавлять блок if для проверки. - person Knight0fDragon; 25.07.2016
comment
@Knight0fDragon: Если вы переопределите инициализацию, как в примере, вы не сможете вызывать GameScene(fileNamed:"GameScene") из GameViewController. Документы Apple ясны: didMove — правильное место для установки сцены. - person Luca Angeletti; 25.07.2016
comment
@appzYourLife, да, вы можете, чтобы получить доступ к удобным методам, вам нужно переопределить все назначенные инициализации - person Knight0fDragon; 25.07.2016
comment
@appzYourLife, к сожалению, когда дело доходит до Sprite Kit, документация ужасна, и Apple рекомендует вещи, которые на самом деле не нужны. Я уже упомянул 2 причины, по которым не всегда хорошо использовать didMove для настройки вашей сцены. - person Knight0fDragon; 25.07.2016
comment
@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)? Я хотел бы провести некоторые тесты. - person Luca Angeletti; 25.07.2016
comment
Давайте продолжим обсуждение в чате. - person Knight0fDragon; 25.07.2016
comment
@appzYourLife необходимый.init не запускает мой код. Я пытался изменить backgroundColor, но он не изменится. Но если я добавлю свой код к двум другим инициализациям, он изменит цвет. Итак, какой из них я должен использовать? - person pRivaT3 BuG; 25.07.2016
comment
@pRivaT3BuG: Это длинная история. --Решение 1--) Просто используйте didMove --Решение 2--: прочитайте мой чат с @Knight0fDragon - person Luca Angeletti; 25.07.2016
comment
@appzYourLife Я прочитал это... слишком сложно для меня, я думаю :P Я прочитаю это еще раз более внимательно. Спасибо за ваше время оба :) - person pRivaT3 BuG; 25.07.2016
comment
@pRivaT3BuG, это потому, что вы используете GameScene(size:) Поместите туда свой код (я уже прокомментировал, что вы все равно не должны его использовать) - person Knight0fDragon; 25.07.2016
comment
@Knight0fDragon Вот что я написал в своем GameViewController: пусть skView = self.view as! SKView --- let scene = GameScene() --- scene.scaleMode = .resizeFill --- skView.presentScene(scene) - person pRivaT3 BuG; 25.07.2016
comment
если вы используете init(), вы помещаете код в метод init(), который вы переопределяете - person Knight0fDragon; 25.07.2016
comment
или, упростите себе жизнь, создайте новый метод для установки и пусть все 3 init вызывают метод установки - person Knight0fDragon; 25.07.2016
comment
@Knight0fDragon Хорошо. Мне понравился последний комментарий. Вот что я собираюсь сделать. Спасибо :) - person pRivaT3 BuG; 25.07.2016