单个自定义对象的Swift NSCoding问题

时间:2016-02-12 04:02:44

标签: ios xcode swift nscoding nskeyedunarchiver

我正在阅读其他一些帖子,我似乎无法弄清楚为什么使用NSKeyedUnarchiver保存到磁盘的对象总是在控制台上打印空白行。我的最终目标是使用NSKeyedArchiver将单个用户对象存储到磁盘。

我目前正在学习如何使用Firebase存储一些数据。我有一个代表用户的自定义类,如下所示:

class User: NSObject, NSCoding {
let key: String
let email: String
let familyKey: String
let username: String
let provider: String
let role: String



// Initialize from arbitrary data
init(key: String, email: String, fKey: String, uName:String, provider:String, role: String) {
    self.key = key
    self.email = email
    self.familyKey = fKey
    self.username = uName
    self.provider = provider
    self.role = role
    super.init()
}

required init?(coder aDecoder: NSCoder) {
    self.key = aDecoder.valueForKey("key") as! String
    self.email = aDecoder.valueForKey("email") as! String
    self.familyKey = aDecoder.valueForKey("familyKey") as! String
    self.username = aDecoder.valueForKey("username") as! String
    self.provider = aDecoder.valueForKey("provider") as! String
    self.role = aDecoder.valueForKey("role") as! String
}
func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(self.key, forKey: "key")
    aCoder.encodeObject(self.email, forKey: "email")
    aCoder.encodeObject(self.familyKey, forKey: "familyKey")
    aCoder.encodeObject(self.username, forKey: "username")
    aCoder.encodeObject(self.provider, forKey: "provider")
    aCoder.encodeObject(self.role, forKey: "role")
}

在我的注册视图控制器中,我创建了用户并使用Firebase对用户进行了身份验证,没有任何问题。在身份验证块中,我使用上面的第一个自定义初始化程序初始化用户对象。我已经尝试过以下方法来保存它,所以我相信我的问题在于我上面的代码中的数据编码/解码,因为这些都不起作用。

根据HackingWithSwift中的此链接在本地归档文件。 FBPath.shared.docDir只是我的doc目录的NSString链接。

let userPath = FBPath.shared.docDir.stringByAppendingPathComponent("currentUser")
                    let userData = NSKeyedArchiver.archivedDataWithRootObject(newUser)
                    userData.writeToFile(userPath, atomically: true)

尝试使用

检索此内容
let userPath = FBPath.shared.docDir.stringByAppendingPathComponent("currentUser")
    if let user = NSKeyedUnarchiver.unarchiveObjectWithFile(userPath) as? User {
        print(user.username)
    }

这不起作用所以我尝试使用Whasssaaahhh post by Whasssaaahhh的帖子将其存储到磁盘上。这是实际工作的代码,但存储了一个emtpy文件。

required convenience init?(coder aDecoder: NSCoder) {

    guard let aKey = aDecoder.decodeObjectForKey("userKey") as? String else {return nil}
    guard let anEmail = aDecoder.decodeObjectForKey("userEmail") as? String else {return nil}
    guard let aFamilyKey = aDecoder.decodeObjectForKey("usersFamilyKey") as? String else {return nil}
    guard let userName = aDecoder.decodeObjectForKey("username") as? String else {return nil}
    guard let aProvider = aDecoder.decodeObjectForKey("userProvider") as? String else {return nil}
    guard let aRole = aDecoder.decodeObjectForKey("userRole") as? String else {return nil}

    self.init(key: aKey, email: anEmail, fKey: aFamilyKey, uName:userName, provider:aProvider, role: aRole)
}

private class func getCurrentUserURL() -> NSURL {
    let documentsDirectory = NSFileManager().URLsForDirectory((.DocumentDirectory), inDomains: .UserDomainMask).first!
    let userPath = documentsDirectory.URLByAppendingPathComponent("currentUser")
    return userPath
}

class func saveCurrentUserToDisk(user:User){
    let success = NSKeyedArchiver.archiveRootObject(user, toFile: User.getCurrentUserURL().path!)
    if !success {
        print("failed to save user to disk")
    }
}
class func loadCurrentUserFromDisk() -> User?{
    return NSKeyedUnarchiver.unarchiveObjectWithFile(User.getCurrentUserURL().path!) as? User
}

在我注册VC以将用户存储到磁盘:

let newUser = User(key: authData.uid, email: self.emailField.text!, fKey: newFamily.key, uName: self.usernameField.text!, provider: authData.provider, role: "parent")
                    newUser.createUserRecords()
                    User.saveCurrentUserToDisk(newUser)

然后尝试访问数据:

if let user = User.loadCurrentUserFromDisk() {
        print(user)
    }

见下文编辑这会打印一个空白行。我不知道如何将此用户保存到磁盘。基于这种尝试,似乎尝试将其保存在用户默认值中并且将其如此小的数据集保存为单个用户并不是一个好主意,无论如何都不会将数据对象存储在磁盘上。只需要找出为什么我不能让这个工作。我还尝试将所有实例变量从let更新为var并将“”指定为字符串值。我希望第二组眼睛可以帮助我看到我在这里失踪的东西。提前谢谢!

编辑:当我将实例变量更改为vars并将其值设置为空字符串时,现在没有返回该对象,并且没有任何内容打印到控制台。如果我更改它们然后用户打印一个空行到控制台,尽管我没有覆盖描述。如果我尝试打印实例变量,它也会再次打印一个空字符串。

所以我也决定检查位置。价值都在那里。它只是没有使用NSKeyedUnarchiver恢复它们。我打印了文件位置以验证它是否正在尝试访问正确的位置,一切都很好。文档的XML在这里没有很好地显示。我是网站新手,我不相信我可以上传文件。但是我仔细查看了生成的plist和它的所有内容。我不会放弃这个,只是手动将数据存储到plist。与NSKeyedArchiver的优势和使用NSCoding相比,不确定可能导致哪些问题

1 个答案:

答案 0 :(得分:0)

问题在于警卫声明停止了未归档对象的初始化。我从guard语句更改为让语句分配一个空字符串,如果它不能像迈克尔在上面的注释中建议的那样解码该值。这有助于我找到具有不正确密钥的值,以便我可以更新代码。一切都很好。