ios - SpriteKit : Why does it wait one round for the score to update?( swift )

标签 ios swift sprite-kit nsuserdefaults

在一个场景中,我有这样的代码:

let defaults = NSUserDefaults.standardUserDefaults()
defaults.setInteger(score, forKey: "scoreKey")

defaults.synchronize()

当用户接触到间隙时,代码运行:

 score++

如果用户撞到障碍物,GameOverScene 将接管。这是我为 GameOverScene 将分数移动到场景到场景的代码:

let defaults = NSUserDefaults.standardUserDefaults()
let score = defaults.integerForKey("scoreKey")
scoreLabel.text = "\(score)"

但是,我的代码中存在一个错误,即 scoreLabel 不更新其文本。例如,假设用户得分为 1 并死亡。当他死了,gameOverScene 会出现并说得分是 1。然后,假设用户点击重新启动,得分为 5,然后死了。在 GameOverScene 中,scoreLabel 将显示为 1。

请帮帮我!

最佳答案

如果您使用 iOS 8 或更高版本,则无需再真正调用同步。这是 Apple 推荐的,但很多人仍然这样做。因此,如果您仍然使用它,请删除该行。

我首选的游戏数据方式是使用带有 NSCoding 的单例 GameData 类。无需到处添加变量,而且更干净。我建议你读这个。

http://www.raywenderlich.com/63235/how-to-save-your-game-data-tutorial-part-1-of-2

您也可以通过这种方式集成 iCloud 键值存储,这非常简单,因为它类似于用户默认设置(请参见下面我的示例)

无论如何,这里是一个简单的例子,说明了它的外观。

import Foundation


/// Keys
private struct Key {
    static let encodedData = "encodedData"
    static let highScore = "highScore"
}

class GameData: NSObject, NSCoding {

// MARK: - Static Properties

/// Shared instance
static let shared: GameData = {
     if let decodedData = UserDefaults.standard.object(forKey: Key.encodedData) as? GameData {
        return gameData
    } else {
        print("No data, creating new")
        return GameData()
    }
}    

// MARK: - Properties

/// Defaults
private let localDefaults = UserDefaults.standard
private let iCloudDefaults = NSUbiquitousKeyValueStore.default()

/// Progress (not saved, no need for saving the score because of the highScore var. Still have here for global single access)
var score = 0

/// Progress (saved)
var highScore = 0

// MARK: - Init
private override init() {
    super.init()
    print("GameData init")
    NotificationCenter.default.addObserver(self, selector: #selector(updateFromCloud), name: NSUbiquitousKeyValueStore.didChangeExternallyNotification, object: iCloudDefaults)
    iCloudDefaults.synchronize()
}

// MARK: - Convenience Init
convenience required init?(coder decoder: NSCoder) {
    self.init()
    print("GameData convenience init")

    // Progress
    highScore = decoder.decodeInteger(forKey: Key.highScore)
}

// MARK: - Encode
func encodeWithCoder(encoder: NSCoder) {

    // Progress
    encoder.encodeInteger(highScore, forKey: Key.highScore)

// MARK: - User Methods

/// Save
func save() {

    if score > highScore {
        highScore = score
    }

    saveLocally()
    saveToCloud()
}

// MARK: - Internal Methods

/// Save locally
private func saveLocally() {
    let encodedData = NSKeyedArchiver.archivedDataWithRootObject(self)
    localDefaults.setObject(encodedData, forKey: Key.encodedData)
}

/// Save to icloud
private func saveToCloud() {
    print("Saving to iCloud")

    // Highscores
    if (highScore > iCloudDefaults.objectForKey(Key.highScore) as? Int ?? Int()) {
        iCloudDefaults.setObject(highScore, forKey: Key.highScore)
    }


/// Update from icloud
func updateFromCloud() {
    print("Updating from iCloud")

    // Highscores
    highScore = max(highScore, iCloudDefaults.object(forKey: Key.highScore) as? Int ?? Int())

    // Save
    saveLocally()
}

现在在任何场景中,如果你想使用分数或保存的 highScore 属性,你可以说

GameData.shared.score++

scoreLabel.text = "\(GameData.shared.score)"
highScoreLabel.text = "\(GameData.shared.highScore)"

如果您转换到新场景或更新 .text 属性,您所有的文本标签将立即更新。不需要 userDefault 同步等。

调用 ...shared... 也将初始化助手。如果您想在游戏启动后立即加载游戏数据,您可以调用

GameData.shared

在您的 appDelegate 或 viewController 中。它可能不是真正需要的,但您仍然可以这样做,只是为了确保在游戏启动后立即初始化助手。

如果你想保存你打电话

GameData.shared.save()

请记住在 ViewDidLoad 方法中将 gameScene.swift 中的分数重置为 0。

GameData.shared.score = 0

这应该会让您的生活更轻松。如果你想使用 iCloud,你所要做的就是转到你的目标和功能并打开 iCloud 并勾选 keyValueStorage(不是核心数据)。完成。

注意: 要更进一步,您可以从 gitHub 上的 JRendel 获取 KeychainWrapper 助手。与使用 NSUserDefaults 存储编码的游戏数据相比,您使用钥匙串(keychain),它非常简单易用。

关于ios - SpriteKit : Why does it wait one round for the score to update?( swift ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33684540/

相关文章:

ios - 重启游戏时FPS不断下降

ios - iOS 的横向滚动 "map"或 "level"游戏

ios - 从另一个 View 重新加载 TableView

ios - iOS 中两个位置之间的估计时间

ios - 无法使用嵌入到我的项目中的 ios-charts 库分发内部构建

php - 从 MYSQL 点转换为 Swift CLLocationCoordinate2D

swift - 如何在 SwiftUI WidgetKit 占位符中自定义占位符外观?

swift - 使用SKScene制作通用应用程序

ios - UIImageWriteToSavedPhotosAlbum()不保存裁剪的图像

ios - 使用 dispatch_semaphore 时泄漏