在iOS中将json保存在应用中的最佳方法是什么?

时间:2019-12-04 06:15:52

标签: swift

我正在使用一个很大的json。将其作为api响应需要花费很多时间。我想获取一次并将其保存在本地,以便可以在我的应用程序中使用它。我想将其保存在文件中,但问题是我应该将该文件存储在哪里。

2 个答案:

答案 0 :(得分:2)

这是我在这种情况下的工作。

首先,我在邮递员上运行API,然后复制JSON并将其粘贴到here。然后指定一个对象名称,并将代码模板选择为swifty JSON,因为您可以使用SwiftyJSON,这使得处理JSON对象非常容易。现在,您可以下载所有类文件并将其添加到您的项目中。那么您需要创建一个新文件,该文件将处理将JSON文件存储和提取到文档目录的过程,看起来像这样:

import Foundation

/// `Cacher` is a super simple cross platform solution to persist `Cachable` types into the filesystem.
final public class Cacher {
    /// The path in the filesystem that will hold all the persisted items
    let destination: URL
    private let queue = OperationQueue()

    /// A type for the type of persistance options.
    ///
    /// - temporary: stores `Cachable` types into the temporary folder of the OS.
    /// - atFolder: stores `Cachable` types into a specific folder in the OS.
    public enum CacheDestination {
        /// Stores items in `NSTemporaryDirectory`
        case temporary
        /// Stores items at a specific location
        case atFolder(String)
    }

    // MARK: Initialization

    /// Initializes a newly created `Cacher` instance using the specified storage destination.
    /// *Note* If using `.atFolder(String)` make sure the destination is valid.
    ///
    /// - Parameter destination: path to the location where `Cacher` will persist its `Cachable` items.
    public init(destination: CacheDestination) {
        switch destination {
        case .temporary:
            self.destination = URL(fileURLWithPath: NSTemporaryDirectory())
        case .atFolder(let folder):
            let documentFolder = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
            self.destination = URL(fileURLWithPath: documentFolder).appendingPathComponent(folder, isDirectory: true)
        }

        try? FileManager.default.createDirectory(at: self.destination, withIntermediateDirectories: true, attributes: nil)
    }

    // MARK

    /// Store a `Cachable` object in the directory selected by this `Cacher` instance.
    ///
    /// - Parameters:
    ///   - item: `Cachable` object to persist in the filesystem
    ///   - completion: callback invoked when the persistance finishes, it will either contain the `URL` of the persisted item, or the `Error` raised while trying to.
    public func persist(item: Cachable, completion: @escaping (_ url: URL?, _ error: Error?) -> Void) {
        var url: URL?
        var error: Error?

        // Create an operation to process the request.
        let operation = BlockOperation {
            do {
                url = try self.persist(data: item.transform(), at: self.destination.appendingPathComponent(item.fileName, isDirectory: false))
            } catch let persistError {
                error = persistError
            }
        }

        // Set the operation's completion block to call the request's completion handler.
        operation.completionBlock = {
            completion(url, error)
        }

        // Add the operation to the queue to start the work.
        queue.addOperation(operation)
    }

    /// Load cached data from the directory
    ///
    /// - Parameter fileName: of the cached data stored in the file system
    /// - Returns: the decoded cached data (if any)
    public func load<T: Cachable & Codable>(fileName: String) -> T? {
        guard
            let data = try? Data(contentsOf: destination.appendingPathComponent(fileName, isDirectory: false)),
            let decoded = try? JSONDecoder().decode(T.self, from: data)
            else { return nil }
        return decoded
    }

    // MARK: Private

    private func persist(data: Data, at url: URL) throws -> URL {
        do {
            try data.write(to: url, options: [.atomicWrite])
            return url
        } catch let error {
            throw error
        }
    }
}

/// A type that can persist itself into the filesystem.
public protocol Cachable {
    /// The item's name in the filesystem.
    var fileName: String { get }

    /// Returns a `Data` encoded representation of the item.
    ///
    /// - Returns: `Data` representation of the item.
    func transform() -> Data
}

extension Cachable where Self: Codable {
    public func transform() -> Data {
        do {
            let encoded = try JSONEncoder().encode(self)
            return encoded
        } catch let error {
            fatalError("Unable to encode object: \(error)")
        }
    }
}

还要再创建一个结构:

struct CachableObject: Cachable, Codable {

    let fileName: String
    let value: JSON
}

现在将需要此struct来存储和获取数据。

从服务器获取数据后,可以使用以下命令将其存储在文档目录中:

let cacher: Cacher = Cacher(destination: .temporary)
let cachableText = CachableObject(fileName: "yourfilename", value: jsonresponse)
cacher.persist(item: cachableText) { url, error in
    if let error = error {
        print("Text failed to persist: \(error)")
    } else {
        print("Text persisted in \(String(describing: url))")
    }
}

现在,它存储在您的文档目录中。

如果您想再次获取完整的JSON,则可以使用:

if let data: CachableObject = cacher.load(fileName: "yourfilename") {
    let jsonData = data.value
    self.yourCustomObject = YourCustomObject.init(fromJson: jsonData)
}

您可以将其与具有不同文件名的任意数量的API一起使用,并可以存储完整的JSON

答案 1 :(得分:0)

您可以将其存储为应用程序目录中的文本文件

let file = "jsonResponse.txt"

let text = "<Json String>"




func writeFile(text : String){

    if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {

        let fileURL = dir.appendingPathComponent(file)

        //writing
        do {
            try text.write(to: fileURL, atomically: false, encoding: .utf8)
        }
        catch {}


    }
}


func readFile() -> Sting{

    if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
        let fileURL = dir.appendingPathComponent(file)

        //reading
    do {
        let text2 = try String(contentsOf: fileURL, encoding: .utf8)

        return text2
    }
    catch {}
    }

    return ""


}

相应地调用writeFile和ReadFile函数