使用UserDefaults

时间:2017-06-25 18:40:08

标签: ios swift sprite-kit nsuserdefaults skscene

在我与Swift一起开发的游戏中,我希望玩家能够在类似商店的场景中选择背景,从而改变每个SKScene的背景。我尝试使用UserDefaults来完成此操作,但由于某种原因它无法正常工作。这是商店场景的重要代码(我删除了不相关的代码):

import SpriteKit

class ShopScene: SKScene {

var backNumber = 90
var backRemainder = 0
var background = SKSpriteNode()
var backName:String = "back1"

override func didMove(to view: SKView) {

    background.texture = SKTexture(imageNamed: "\(backName)")
    background.size = self.size
    self.addChild(background)

    let nextButton: NButton = NButton(defaultButtonImage: "next", activeButtonImage: "nextP", buttonAction: nextAction)
    addChild(nextButton)

    let selectButton: SButton = SButton(defaultButtonImage: "next", activeButtonImage: "nextP", buttonAction: selectAction)
    addChild(selectButton)   
}

func selectAction() {

    UserDefaults.standard.set(backName, forKey: "backSaved")

    let sceneToMoveTo = MainMenuScene(size: self.size)
    sceneToMoveTo.scaleMode = self.scaleMode
    let sceneTransition = SKTransition.fade(withDuration: 0.4)
    self.view!.presentScene(sceneToMoveTo, transition: sceneTransition)   
}

func nextAction() {

    backNumber += 1
    backRemainder = backNumber % 3

    switch backRemainder {
    case 0:
        backName = "back1"
    case 1:
        backName = "back2"
    case 2:
        backName = "back3"
    default:
        backName = "back1"
    }

    background.texture = SKTexture(imageNamed: "\(backName)")
}
}

如您所见,当按下选择按钮时,将保存名称。现在,这是主菜单场景的相关代码:

Import SpriteKit

class MainMenuScene: SKScene {

var backName = UserDefaults.standard.string(forKey: "backSaved")

override func didMove(to view: SKView) {

    let background = SKSpriteNode(imageNamed: "\(backName)")
    background.size = self.size
    self.addChild(background)

当选择'按下按钮,您应该转换到主菜单场景,并看到背景是您选择的背景。但是,当我运行它时,我在白色背景中得到一个红色的X.我之前曾在UserDefaults工作过以节省分数,但我无法弄清楚为什么它在这种情况下不起作用。有关如何使用UserDefaults在SKScenes之间传递字符串的任何想法?我做错了吗?

注意:虽然Knight0fDragon的答案标记正确,但他的答案适用于在场景之间传递字符串,但不能永久保存该值。如果您希望传递该值并保存,请检查我的答案。

2 个答案:

答案 0 :(得分:2)

我建议不要执行UserDefaults,这是针对您的应用程序的首选项。而是使用userData

func selectAction() {

    let sceneToMoveTo = MainMenuScene(size: self.size)
    sceneToMoveTo.scaleMode = self.scaleMode
    sceneToMoveTo.userData = sceneToMoveTo.userData ?? NSMutableDictionary() //This lets us ensure userdata exists
    sceneToMoveTo.userData!["backSaved"] = backName
    let sceneTransition = SKTransition.fade(withDuration: 0.4)
    self.view!.presentScene(sceneToMoveTo, transition: sceneTransition)   
}

然后用:

实现它
import SpriteKit

class MainMenuScene: SKScene {



lazy var backName:String = {return self.userData?["backSaved"] as? String ?? "back1"}() //This allows us to load backName at the time it is needed, or assign back1 if doesn't exist

override func didMove(to view: SKView) {


    let background = SKSpriteNode(imageNamed: backName)
    self.addChild(background)
注意,我不确定是否如此?需要字符串,没有它就可以尝试,看看Swift是否可以推断它

答案 1 :(得分:0)

显然,backName表现为可选,因为它没有值,因此为零。为了使我的代码工作,我对Shop Scene进行了这些更改:

import SpriteKit

class ShopScene: SKScene {

var backName:String? = UserDefaults.standard.string(forKey: "backSaved")

override func didMove(to view: SKView) {

    if backName != nil {
        backName = UserDefaults.standard.string(forKey: "backSaved")
    } else {
        backName = "back1"
    }

    background.texture = SKTexture(imageNamed: "\(backName!)")
    self.addChild(background)

并对主菜单场景进行了这些更改:

import SpriteKit

class MainMenuScene: SKScene {

var backName:String? = UserDefaults.standard.string(forKey: "backSaved")

override func didMove(to view: SKView) {

    if backName != nil {
        backName = UserDefaults.standard.string(forKey: "backSaved")
    } else {
        backName = "back1"
    }

    let background = SKSpriteNode(imageNamed: "\(backName!)")
    self.addChild(background)