簡體   English   中英

如何保存來自用戶登錄核心數據的 JSON 響應以跟蹤 Swift 中的用戶 state?

[英]How to save JSON response from user login into Core Data to track the user state in Swift?

我正在嘗試將來自用戶登錄的 json 響應保存到 Core Data,以便當用戶退出應用程序並再次打開時,它將識別該特定用戶。 我只有簡單的 json,它是 ["String":Any, ...."String":Any] 類型,現在我通過制作 model 的結構來保存響應,如下所示,有人知道實現什么的最佳方法嗎我想要,請幫助我我是 Core Data 的新手,我不知道從哪里開始

這是我請求和保存 json 的方式

這是我的 LoginInfo 模型

這是我的核心數據實體

拳頭聲明你的核心數據容器

//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將是您的核心數據文件名。

然后這個 function 將進行保存:

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 文檔和其他一些教程以更好地理解。 還要確保處理上述步驟可能引起的所有錯誤。 我沒有考慮可能發生錯誤的每一種情況。

基礎知識
在 XCode 上創建您的 Swift 項目並檢查Use CoreData
確保在 class 標題上使用import CoreData

保存到 CoreData
如果您的項目使用 CoreData,您可以繼續保存下面的 function:

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 class 中,或者放入 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)
// ...

要檢索 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
}

獲取特定數據

我制作了一個 function,我們可以用它來獲取我們之前保存的任何信息:

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)
}

免責聲明:我沒有測試過上面的代碼,如果你遇到任何錯誤,請在評論中告訴我。
編輯:更新fetchReq並替換了getAnyValueFromCoreData()中的filterReq (自制函數)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM