如何将用户登录的 JSON 响应保存到 Core Data 中以跟踪 Swift 中的用户状态?
Posted
技术标签:
【中文标题】如何将用户登录的 JSON 响应保存到 Core Data 中以跟踪 Swift 中的用户状态?【英文标题】:How to save JSON response from user login into Core Data to track the user state in Swift? 【发布时间】:2021-03-08 05:53:45 【问题描述】:我正在尝试将来自用户登录的 json 响应保存到 Core Data 中,以便当用户退出应用程序并再次打开时,它会识别该特定用户。我只有简单的 json,它是 ["String":Any, .... "String":Any] 类型,现在我通过制作如下结构模型来保存响应,谁能知道实现什么的最佳方法我想要,请帮帮我 我是 Core Data 的新手,我不知道从哪里开始
【问题讨论】:
print(loginData)
打印的信息是否正确?
是的,它会打印json的登录ingo
邮政编码为文字而非图片
你应该先做一些教程和阅读一些关于 Core Data 的文章,因为 *** 不是一个教程网站,所以这个问题很广泛,应该关闭。
是的,我阅读了苹果文档,他们关于如何使用 CoreData 的示例很难理解这个概念,所以我搜索了有用的教程网但没有成功,最后一个选项是询问 ***,
【参考方案1】:
首先声明你的核心数据容器
//CoreData container
private lazy var persistentContainer: NSPersistentContainer =
let container = NSPersistentContainer(name: "container_name")
container.loadPersistentStores(completionHandler: (storeDescription, error) in
if let error = error
//Error handling
)
return container
()
这里container_name
将是您的核心数据文件名。
然后这个函数会做保存:
public func saveLoginData(data: LoginData)
let context: NSManagedObjectContext = self.persistentContainer.viewContext
let entityDescription: NSEntityDescription = NSEntityDescription.entity(forEntityName: "LoginInfo", in: context)!
let loginInfoEntry: NSManagedObject = NSManagedObject(entity: entityDescription, insertInto: context)
//Set your values here
loginInfoEntry.setValue(data.AccountId, forKey: "accountId")
loginInfoEntry.setValue(data.UserId, forKey: "userId")
... //Set all your values
//Then save
do
try context.save()
catch
//Error handling
查询您的数据:
public func getLoginData() -> LoginData?
let context: NSManagedObjectContext = self. persistentContainer.viewContext
let loginDataFetchRequest: NSFetchRequest = NSFetchRequest<NSManagedObject>(entityName: "LoginInfo")
do
let fetchedData: [Any] = try context.fetch(loginDataFetchRequest)
let loginDataObjectArray: = fetchData as! [NSManagedObject]
let loginDataObject: NSManagedObject = loginDataObjectArray[0]
var loginData: LoginData = LoginData()
loginData.AccountId = loginDataObject.value(forKey: "accountId") as! String
...//Set all your values
return loginData
catch
//Handle errors
return nil
这只是对您的问题的一个简单回答,为您指明方向。请参阅 CoreData 文档和其他一些教程以更好地理解。还要确保处理上述步骤可能引起的所有错误。我没有考虑可能发生错误的每一种情况。
【讨论】:
感谢您的帮助,但是对于查询,它不起作用,因为 LoginData 是可解码协议,它说它会引发错误并且我在查询时无法创建 LoginData 的新实例,是有什么办法吗? 我更新了答案。var loginData: LoginData = LoginData()
。你能显示错误吗
它在var loginData: LoginData = LoginData()
中说“在调用中缺少参数'from'的参数”我应该给一些解码器的LoginData()一个参数,这是错误
仅使用print(loginDataObject.value(forKey: "accountId") as! String)
而不创建 loginData 来检查查询中的值是否正确。
chat.***.com/rooms/229646/…来聊天【参考方案2】:
基础知识
在 XCode 上创建您的 Swift 项目并检查 Use CoreData
确保在您的课程标题上使用import CoreData
保存到 CoreData 如果您的项目使用CoreData,您可以继续使用下面的保存功能:
func saveLoginDataToCoreData(data: LoginData)
guard let appDel = UIApplication.shared.delegate as? AppDelegate else return
let context = appDel!.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "LoginInfo", in: context)!
let mngdObj = NSManagedObject(entity: entity, insertInto: context)
mngdObj.setValue(data.LoginToken, forKeyPath: "loginToken")
mngdObj.setValue(data.UserId, forKeyPath: "userId")
// Add all loginData here...
do try context.save(); print("LoginData has been saved to CoreData")
catch print("An error has occurred: \(error.localizedDescription)")
另一方面,如果您的项目不使用 CoreData,您可以声明一个名为“CoreData Stack”的 CoreData 容器(这会自动包含在 AppDelegate 中使用 CoreData 的项目中)。您可以将它放在需要它的 ViewController 类中,或者放入 UIViewController 扩展中以供全局使用:
lazy var persistentContainer: NSPersistentContainer =
let container = NSPersistentContainer(name: "Your_DataModel_Filename")
container.loadPersistentStores(completionHandler: (storeDescription, error) in
if let error = error as NSError?
print("An error has occurred: \(error.localizedDescription)")
)
return container
()
使用方法:
func saveLoginDataToCoreData(data: LoginData)
let context: NSManagedObjectContext = self.persistentContainer.viewContext
let entity: NSEntityDescription = NSEntityDescription.entity(forEntityName: "LoginInfo", in: context)!
let mngdObj: NSManagedObject = NSManagedObject(entity: entity, insertInto: context)
mngdObj.setValue(data.LoginToken, forKeyPath: "loginToken")
mngdObj.setValue(data.UserId, forKeyPath: "userId")
// Add all loginData here...
do try context.save(); print("LoginData has been saved to CoreData")
catch print("An error has occurred: \(error.localizedDescription)")
更新:后续答复
如果您想使用该 loginToken 或 LoginData 中的任何数据,我们可以获取我们之前从 CoreData 中保存的值。
为了有效地检索值,最好先保存当前用户的 LoginToken。为方便访问,建议登录时保存在UserDefaults
,注销时删除即可。
func saveCurrentLoginToken(_ token:String)
let defaults = UserDefaults.standard
defaults.set(token, forKey: "currentLoginToken")
defaults.synchronize()
示例用法:
// ...
let currentLoginToken = data.LoginToken
mngdObj.setValue(currentLoginToken, forKeyPath: "loginToken")
self.saveCurrentLoginToken(currentLoginToken)
// ...
获取当前登录令牌:
func getCurrentLoginToken() -> String?
let defaults = UserDefaults.standard
let token = defaults.object(forKey: "currentLoginToken") as? String
if token != nil return token! // Return value if not nil
else return nil // Will return as nil if you haven't save the LoginToken in UserDefaults
获取特定数据
我创建了一个函数,我们可以使用它来获取我们之前保存的任何信息:
func getAnyValueFromCoreData(_ loginToken:String,_ key:String) -> Any? // key = data you want to retrieve the value of
guard let appDel = UIApplication.shared.delegate as? AppDelegate else return nil
let context = appDel.persistentContainer.viewContext
let fetchReq = NSFetchRequest<NSManagedObject>(entityName: "LoginInfo")
fetchReq.predicate = NSPredicate(format: "loginToken==%@",loginToken)
var anyVal: Any?
do let result = try context.fetch(fetchReq)
for data in result
let val = data.value(forKey: key)
// Check if nil to avoid fatal error
if val != nil anyVal = val! else anyVal = nil
catch
anyVal = nil // Set value to nil in case of error (not always recommended)
print("An error has occurred: \(error.localizedDescription)")
return anyVal
现在,例如,如果您想获取当前用户的 ReturnCode:
func getReturnCode() -> Int?
let token = getCurrentLoginToken() // retrieve from UserDefaults
let returnCode = getAnyValueFromCoreData(token!,"returnCode") as? Int
return returnCode
使用(在您在评论中描述的情况下):
func checkReturnCode()
let returnCode = getReturnCode()! // catch if nil?
if returnCode == 0
// show MainPage to User
else
// or use Switch Statements for more than two ReturnCodes
// or to handle error in case of default (nil value)
免责声明:我没有测试上面的代码,如果你遇到任何错误,请在 cmets 中告诉我。编辑:更新 @987654333 @并把filterReq
替换成getAnyValueFromCoreData()
(自制函数)
【讨论】:
谢谢,它工作得很好,但后来如果我想使用该 loginTokens 或 LoginData 中的任何数据,我该如何检索它?例如在另一个 vc 中,如果 returnCode == 0,则向用户显示主页。 我已更新我的答案以解决您的后续问题。请让我知道它是否有效 我认为它有一些错误,我已经搜索了互联网但找不到解决方案,它在getAnydatafromCoredata()
方法中显示Cannot find 'fetchEntity' in scope
和Cannot find 'filterReq' in scope
@Ulugbek,抱歉,这些是我忘记包含的自制功能。将更新我的答案
是的,不用担心,我非常感谢您的帮助,现在通过查看代码并且我了解流程,我期待您的更新,以上是关于如何将用户登录的 JSON 响应保存到 Core Data 中以跟踪 Swift 中的用户状态?的主要内容,如果未能解决你的问题,请参考以下文章
如果 JSON 响应结果为 0/11,我如何将用户发送到 servlet 中的 .html 页面
如何在您的登录 api 的 Json 响应后重定向用户反应本机