首页 > 解决方案 > 如何快速保存 Json 数据并离线显示

问题描述

我正在尝试保存我的 json 文件并将其显示为离线。我正在尝试这段代码,但它对我不起作用..

let myData = NSKeyedArchiver.archivedData(withRootObject: self.data)
             UserDefaults.standard.set(myData, forKey: "userJson")
             UserDefaults.standard.synchronize()

谁能建议我更好的方法来保存数据和离线炫耀?

标签: iosjsonswift

解决方案


您不应该将 JSON 保存在 UserDefault 中,而是将其保存在文档目录中的文件中

我创建了通用类,可以轻松完成

//
//  OfflineManager.swift
// 
//
//  Created by Prashant on 01/05/18.
//  Copyright © 2018 Prashant. All rights reserved.
//

import UIKit

class OfflineManager: NSObject {

    static let sharedManager = OfflineManager()
    let LocalServiceCacheDownloadDir        = "LocalData"

    enum WSCacheKeys {
        case CampignList
        case CampignDetail(id:String)
        case ScreenShotList

        var value:String {
            switch self {
            case .CampignList:
              return  "CampignList"
            case .CampignDetail(let id):
                return id
            case .ScreenShotList :
                return "ScreenShotList"
            }

        }
    }

    func getBaseForCacheLocal(with fileName:String) -> String? {

        let filePath = FileManager.default.getDocumentPath(forItemName: self.LocalServiceCacheDownloadDir)
        if FileManager.default.directoryExists(atPath: filePath) {
            return filePath.stringByAppendingPathComponent(fileName)
        } else {
            if  FileManager.default.createDirectory(withFolderName: self.LocalServiceCacheDownloadDir) {
                return filePath.stringByAppendingPathComponent(fileName)
            }
        }
        return nil
    }



    //------------------------------------------------------------

    @discardableResult
    func cacheDataToLocal<T>(with Object:T,to key:WSCacheKeys) -> Bool {
        let success = NSKeyedArchiver.archiveRootObject(Object, toFile: getBaseForCacheLocal(with: key.value)!)
        if success {
            print( "Local Data Cached\(String(describing: getBaseForCacheLocal(with: key.value)))")
        } else {
            print("Error")
        }

        return success

    }

    //------------------------------------------------------------

    func loadCachedDataFromLocal<T>(with key:WSCacheKeys ) -> T? {
        return NSKeyedUnarchiver.unarchiveObject(withFile: getBaseForCacheLocal(with: key.value)!) as? T
    }


    //------------------------------------------------------------


    func removeAllCacheDirs () {
        do {
            try FileManager.default.removeItem(atPath: self.getBaseForCacheLocal(with: "")!)

        } catch {
            print("error in remove dir \(error.localizedDescription)")
        }

    }

    //--------------------------------------------------------------------------------


}

下面是一些辅助方法extension FileManager

public var getDocumentDirectoryPath: String {
    let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    return documentDirectory
}

public func getDocumentPath(forItemName name: String)-> String {
    return getDocumentDirectoryPath.stringByAppendingPathComponent(name)
}

public func directoryExists(atPath filePath: String)-> Bool {
    var isDir = ObjCBool(true)
    return FileManager.default.fileExists(atPath: filePath, isDirectory: &isDir )
}

public func createDirectory(withFolderName name: String)-> Bool {
    let finalPath = getDocumentDirectoryPath.stringByAppendingPathComponent(name)
    return createDirectory(atPath: finalPath)
}

这是字符串扩展的方法

public func stringByAppendingPathComponent(_ path: String) -> String {
    let fileUrl = URL.init(fileURLWithPath: self)
    let filePath = fileUrl.appendingPathComponent(path).path
    return filePath
}

如何使用它 ?

保存

   OfflineManager.sharedManager.cacheDataToLocal(with: object as! [String:Any], to: .CampignList)

读取数据

    DispatchQueue.global().async {
        // GET OFFLINE DATA
        if let object:[String:Any] = OfflineManager.sharedManager.loadCachedDataFromLocal(with: .CampignList) {
            do {
                let data = try  JSONSerialization.data(withJSONObject: object, options: [])
                let object = try CampaignListResponse.init(data: data)
                self.arrCampignList = object.data ?? []
                DispatchQueue.main.async {
                    self.tableVIew.reloadData()
                }
            } catch {
            }
        }
      }

注意:您可以定义自己WSCacheKeys的 json 类型,就像我正在获取一些活动列表一样


推荐阅读