ios - 将多个 userdefaults 变量存储在 spritekit 中的某种数组、类或结构中?

标签 ios swift sprite-kit nsuserdefaults userdefaults

现在游戏玩法有多个级别,每个级别都有一个 secret 元素( bean ),玩家在每个级别、每个保存文件中只能找到一次。这个想法是,如果玩家可以在每个级别找到每个 secret bean ,一旦他们到达游戏结束,他们就会获得奖励。我通过用户默认设置跟踪玩家何时在每个级别找到或没有找到 secret 元素,它有效,但我的实现很丑陋,我需要帮助。

问题是我想不出一种有效的方法来按级别执行此操作。为了跟踪每个级别的所有这些,我一直在这样做:

//Class gameScene variable this tracks per level if the player found the bean, if so then it's set to true and the bean will not load in the level if the player revisits

 var foundBeanLevel1 = UserDefaults().bool(forKey: "FoundBeanLevel1")
 var foundBeanLevel2 = UserDefaults().bool(forKey: "FoundBeanLevel2")

这是在每个级别覆盖 didMove(用 X 级别替换 1):

 if foundBeanLevel1{
    let secretBean: SKSpriteNode = childNode(withName: "SecretBean") as! SKSpriteNode
    secretBean.removeFromParent()
 }

_

//total count, if it's not the sum of the number of levels then the player didn't collect all beans
var secretBeanCount: Int = UserDefaults().integer(forKey: "SavedSecretBean") {
    didSet {
        //sets the increment to user defaults
        UserDefaults().set(secretBeanCount, forKey: "SavedSecretBean")
    }
}

//didContact
if node.name == SecretBean{
    secretBeanCount += 1
    if levelCheck == 1 {
        UserDefaults().set(true, forKey: "FoundBeanLevel1")
    } else if levelCheck == 2 {
        UserDefaults().set(true, forKey: "FoundBeanLevel2")
    }
}

然后如果他们开始新游戏:

UserDefaults().set(0, forKey: "SavedSecretBean")
UserDefaults().set(false, forKey: "FoundBeanLevel1")
UserDefaults().set(false, forKey: "FoundBeanLevel2")

该系统按预期工作,但我知道它非常草率。此外,我获得的级别越多,这些 else if 语句就会变得越大。我知道有更好的方法可以做到这一点,但我不确定在这方面我在寻找什么。任何建议将不胜感激。

最佳答案

扩展 Tom E 关于使用 Sets 并保存到 UserDefaults 的聪明建议,您可能还想将所有其他 GameVariables 保存在一个对象中并轻松使用它。如果您坚持使用 UserDefaults,我建议使用 Codable,这就是实现的样子:

struct GameSceneVariables: Codable {
    let beanLevels: Set<Int>
    let savedSecretBean: Int
}

extension UserDefaults {

    /// Saves a Codable Object into UserDefaults
    ///
    /// - Parameters:
    ///   - object: The object to save that conforms to Codable
    ///   - key: The key to save and fetch
    /// - Returns: if the save was successful or failed
    func set<T:Codable>(_ object: T, key: String) -> Bool {
        guard let encodedValue = try? JSONEncoder().encode(object) else {
            return false
        }
        UserDefaults.standard.set(encodedValue, forKey: key)
        return true
    }

    /// Retrieves a Codable object saved in UserDefaults
    ///
    /// - Parameters:
    ///   - key: The key that was used to save the object into UserDefaults
    ///   - type: The type of the object so that you would not to actually cast the object so that the compiler
    ///           can know what Type of object to Return for the generic parameter T
    /// - Returns: returns the object if found, or nil if not found or if not able to decode the object
    func object<T:Codable>(forKey key: String, forObjectType type: T.Type) -> T? {
        guard let data = UserDefaults.standard.value(forKey: key) as? Data else { return nil }
        return try? JSONDecoder().decode(T.self, from: data)
    }

}

let variables = GameSceneVariables(beanLevels: [0, 1, 2], savedSecretBean: 0)
let userDefaults = UserDefaults.standard
let success = userDefaults.set(variables, key: "GameSceneVariables")
if success {
    let fetchedVariables = userDefaults.object(forKey: "GameSceneVariables", forObjectType: GameSceneVariables.self)
} else {
    // This can happen because the properties might not have been encoded properly
    // You will need to read up more on Codable to understand what might go wrong
    print("Saving was not a success")
}

我添加了关于代码功能的注释。我强烈建议在使用此代码之前阅读 Apple 文档中有关 Codable 的更多信息。

关于ios - 将多个 userdefaults 变量存储在 spritekit 中的某种数组、类或结构中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50586882/

相关文章:

swift - 为什么要通过向量的 sqrt 创建单位向量

swift - 在 Xcode SpriteKit 场景编辑器中向实体添加自定义 GKComponent 将 GKScene.rootNode 设置为 nil

ios - 应用程序 'attaching to' 在 iOS 模拟器中挂起

ios - 我如何从解析中获取数字数据和日期数据并将其放入 UILabel?

ios - Apple id 没有登录 Xcode?

swift - 如何在 uiscrollview 中的按钮之间添加空间

xcode - 无法在单独的项目中引用类型

ios - 如何播放/停止背景音乐和音效?

ios - 无法在 View Controller 中创建 socket /操作

ios - 如何检查当前在哪个 iPhone 设备上运行该应用程序?