从singleton获取可选字符串

时间:2018-02-10 01:47:00

标签: swift string singleton nsuserdefaults optional

我创建了一个带有一些变量和类的类。其中一个变量是String。我将它们存储在UserDefaults中。如果我想通过单例类访问此类的字符串,我将始终获得一个可选的String。我不知道为什么。

这是对象的类:

import Foundation
import SpriteKit

class BallSkinsClass: NSObject, NSCoding {
    let id: Int
    var name: String
    var isBuyed: Bool

    let ID = "id"
    let NAME = "name"
    let ISBUYED = "isBuyed"

    init(id: Int, name: String, isBuyed: Bool) {
        self.id = id
        self.name = name
        self.isBuyed = isBuyed
    }

    required init?(coder aDecoder: NSCoder) {
        self.id = aDecoder.decodeInteger(forKey: ID)
        self.name = String(describing: aDecoder.decodeObject(forKey: NAME))
        self.isBuyed = aDecoder.decodeBool(forKey: ISBUYED)
    }

    @objc func encode(with aCoder: NSCoder) {
        aCoder.encode(id, forKey: ID)
        aCoder.encode(name, forKey: NAME)
        aCoder.encode(isBuyed, forKey: ISBUYED)
    }
}

要声明皮肤,访问,保存和加载我在BallSkinsClass中有这些函数:

import Foundation
import SpriteKit
import GameKit

class BallSkins {
    static var sharedInstance = BallSkins()

    private init() {
    }

    let BALLSKINS = "ballSkins"

    var standard: BallSkinsClass! = BallSkinsClass(id: 0, name: "Standard", isBuyed: true)
    var billiard: BallSkinsClass! = BallSkinsClass(id: 1, name: "Billard", isBuyed: false)
    var emoji: BallSkinsClass! = BallSkinsClass(id: 2, name: "Emojis", isBuyed: false)

    func archiveBallSkins(ballSkins:[BallSkinsClass]) -> NSData {
        print("archiving Skins")
        let archivedBallSkins = NSKeyedArchiver.archivedData(withRootObject: ballSkins as Array)
        return archivedBallSkins as NSData
    }

    func saveBallSkins(ballSkins:[BallSkinsClass]) {
        let archivedBallSkins = archiveBallSkins(ballSkins: ballSkins)
        UserDefaults.standard.set(archivedBallSkins, forKey: BALLSKINS)
        print("saving Skins")
    }

    func retrieveBallSkins() -> [BallSkinsClass]? {
        print("retrieving Skins")
        if let unarchivedBallSkins = UserDefaults.standard.object(forKey: BALLSKINS) as? NSData {
            return NSKeyedUnarchiver.unarchiveObject(with: unarchivedBallSkins as Data) as? [BallSkinsClass]
        }
        return nil
    }

    func loadBallSkins() {
        print("loading Skins")
        let archivedBallSkins = retrieveBallSkins()
        for ballSkin in archivedBallSkins! {
            switch ballSkin.id {
            case 0 :
                standard.isBuyed = ballSkin.isBuyed
            case 1:
                billiard.isBuyed = ballSkin.isBuyed
            case 2:
                emoji.isBuyed = ballSkin.isBuyed
            default:
                standard.isBuyed = ballSkin.isBuyed
            }
        }
    }
}

如果我想访问任何其他场景或视图中的皮肤名称,我会调用:

ballSkins.sharedInstance.billiard.name 

但每次都是可选的!我不知道错误的原因或位置。

1 个答案:

答案 0 :(得分:1)

我想这是由

引起的
required init?(coder aDecoder: NSCoder) {
    self.id = aDecoder.decodeInteger(forKey: ID)
    self.name = String(describing: aDecoder.decodeObject(forKey: NAME))
    self.isBuyed = aDecoder.decodeBool(forKey: ISBUYED)
}

第3行生成可选字符串,因为根据文档

  

func decodeObject() - >任何?

和String(描述:...)不会解开您的值。您必须自己从UserDefaults中解包所有值,如果不可能则提供defaultValue