基于ObjectMapper的本地緩存

公司項(xiàng)目在之前是沒有將首頁數(shù)據(jù)做緩存的,用戶體驗(yàn)不太好,所以現(xiàn)在需要將首頁數(shù)據(jù)存到本地。

實(shí)現(xiàn)

首先考慮用NSKeyedArchiver,但是用這貨需要遵守NSCoding協(xié)議,將模型里的每個屬性確定類型。但我們項(xiàng)目用ObjectMapper解析json,就已經(jīng)把模型中的每個屬性都設(shè)置過映射關(guān)系了,他喵的難道還要我要再寫一遍?
后來仔細(xì)想想,json文件無非就是array和dictionary,只不過其本身的類型由根節(jié)點(diǎn)來確定,而且NSArray和NSDictionary是有writeToFile的方法的,那么我把模型轉(zhuǎn)為對應(yīng)的NSArray和NSDictionary類型就好了啊,bingo~~


擼了半天,代碼如下:

import Foundation
import ObjectMapper

class CacheManager {
    //路徑
    static func filePath(_ fileName:String) -> URL?{
        let manager = FileManager.default
        //往哪存,自己改
        guard let cachePath = manager.urls(for: .cachesDirectory, in: .userDomainMask).first else { return nil }
        let directory = cachePath.appendingPathComponent("buybuyARTCache")
        
        if !manager.fileExists(atPath: directory.path){
            do{
                try manager.createDirectory(atPath: directory.path, withIntermediateDirectories: true, attributes: nil)
            }catch{
                return nil
            }
        }
        let path = directory.appendingPathComponent(fileName)
        return path
    }
    
    @discardableResult
    static func setCache(object:BaseMappable, for fileName: String) -> Bool{
        return setCache(json: object.toJSON(), for: fileName)
    }
    
    /*使用時需顯示聲明類型,let a:Art = CacheManager.cache(for: "cacheName")
     參照http://stackoverflow.com/questions/27965439/cannot-explicitly-specialize-a-generic-function */
    static func cache<T: BaseMappable>(for fileName: String) -> T?{
        guard let jsonDict = cacheJson(for: fileName) as? [String: Any] else {return nil}
        return Mapper<T>().map(JSON: jsonDict)
    }
    
    //存數(shù)組
    @discardableResult
    static func setCache(array: [BaseMappable], for fileName: String) -> Bool{
        return self.setCache(json: array.map({$0.toJSON()}), for: fileName)
    }
    
    //取數(shù)組
    static func cacheArray<T: BaseMappable>(for fileName: String) -> Array<T>?{
        guard let jsonArray = cacheJson(for: fileName) as? [[String: Any]] else {return nil}
        return Mapper<T>().mapArray(JSONArray: jsonArray)
    }
    
    //存json
    @discardableResult
    static func setCache(json: Any, for fileName: String) -> Bool{
        guard let filePath = filePath(fileName) else {return false}
        if let array = json as? [Any]{
            let jsonArray = NSArray(array: array)
            return jsonArray.write(to: filePath, atomically: true)
        }else if let dict = json as? [String: Any]{
            let jsonDict = NSDictionary(dictionary: dict)
            return jsonDict.write(to: filePath, atomically: true)
        }else {
            return false
        }
    }
    
    //取json
    static func cacheJson(for fileName: String) -> Any?{
        guard let filePath = filePath(fileName) else {return nil}
        if let jsonArray = NSArray(contentsOf: filePath){
            return jsonArray
        }else if let jsonDict = NSDictionary(contentsOf: filePath){
            return jsonDict
        }else{
            return nil
        }
    }
}

原則上來說,CacheManager只支持遵循了BaseMappable協(xié)議的對象,因?yàn)槟P投际怯肙bjectMapper解析出來的。但是后來想想,這樣貌似限制太大,所以又加了對json數(shù)據(jù)的緩存。

問題

其中碰到一個問題,就是這個函數(shù)是用來從沙盒里取數(shù)據(jù)的,使用的時候需要確定數(shù)據(jù)的類型

static func cache<T: BaseMappable>(for fileName: String) -> T?{ 
    guard let jsonDict = cacheJson(for: fileName) as? [String: Any] else  {return nil} 
    return Mapper<T>().map(JSON: jsonDict) 
}

但是當(dāng)調(diào)用的時候,編譯器老是編譯不過,提示什么Cannot explicitly specialize a generic function。后來上so查了以后才知道,當(dāng)使用泛型函數(shù)時,如果返回值是關(guān)聯(lián)類型的話,需要顯示聲明

let a:Art = CacheManager.cache(for: "cacheName")

真是學(xué)藝不精~~(⊙﹏⊙)b
代碼不多,就不放github了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容