Swift 单个自定义对象的 NSCoding 问题
Swift NSCoding issue with single custom object
我正在阅读其他一些 posts,但我似乎无法弄清楚为什么在下面使用 NSKeyedUnarchiver 将对象保存到磁盘时总是向控制台打印空白行。我的最终目标是使用 NSKeyedArchiver 将单个用户对象存储到磁盘。
我目前正在学习如何使用 Firebase 来存储一些数据。我有一个自定义 class 代表用户如下:
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 对用户进行了身份验证,没有任何问题。在身份验证块中,我使用上面的第一个自定义初始化程序初始化用户对象。我已经尝试了以下方法来保存它,所以我相信我的问题出在我上面的代码中,因为这些工作 none 之后数据的 encoding/decoding 。
基于来自 HackingWithSwift 的 link 在本地归档文件。 FBPath.shared.docDir 只是一个 NSString link 到我的文档目录。
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 的 post 将其存储到磁盘。这是实际工作的代码,但存储了一个空文件。
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
的好处相比会导致什么问题
问题在于保护语句停止了正在取消存档的对象的初始化。我从 guard 语句更改为 let 语句,如果它无法按照 Michael 在上面的评论中建议的那样解码值,则分配一个空字符串。这帮助我找到了具有不正确键的值,以便我可以更新代码。现在一切都很好。
我正在阅读其他一些 posts,但我似乎无法弄清楚为什么在下面使用 NSKeyedUnarchiver 将对象保存到磁盘时总是向控制台打印空白行。我的最终目标是使用 NSKeyedArchiver 将单个用户对象存储到磁盘。
我目前正在学习如何使用 Firebase 来存储一些数据。我有一个自定义 class 代表用户如下:
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 对用户进行了身份验证,没有任何问题。在身份验证块中,我使用上面的第一个自定义初始化程序初始化用户对象。我已经尝试了以下方法来保存它,所以我相信我的问题出在我上面的代码中,因为这些工作 none 之后数据的 encoding/decoding 。
基于来自 HackingWithSwift 的 link 在本地归档文件。 FBPath.shared.docDir 只是一个 NSString link 到我的文档目录。
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 的 post 将其存储到磁盘。这是实际工作的代码,但存储了一个空文件。
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
的好处相比会导致什么问题问题在于保护语句停止了正在取消存档的对象的初始化。我从 guard 语句更改为 let 语句,如果它无法按照 Michael 在上面的评论中建议的那样解码值,则分配一个空字符串。这帮助我找到了具有不正确键的值,以便我可以更新代码。现在一切都很好。