ObjectMapper 기반 로 컬 캐 시

4254 단어
인도 하 다.
회사 프로젝트 는 이전 에는 홈 페이지 데 이 터 를 캐 시 하지 않 았 기 때문에 사용자 체험 이 좋 지 않 기 때문에 지금 은 홈 페이지 데 이 터 를 로 컬 에 저장 해 야 합 니 다.
이루어지다
우선 NSKeyed Archiver 를 사용 하 는 것 을 고려 하지만 이 물건 을 사용 하려 면 NSCoding 협 의 를 준수 하고 모델 안의 모든 속성 을 유형 을 정 해 야 합 니 다.그러나 우리 프로젝트 는 Object Mapper 로 json 을 분석 하면 모델 의 모든 속성 을 매 핑 관 계 를 설정 한 적 이 있 습 니 다. 그 는 고양이 가 나 에 게 다시 한 번 써 야 합 니까?나중에 생각해 보 니 제 이 슨 파일 은 array 와 dictionary 가 아니 라 그 자체 의 유형 은 루트 노드 에 의 해 확정 되 었 을 뿐 입 니 다. 그리고 NSArray 와 NSDictionary 는 writeToFile 의 방법 이 있 습 니 다. 그러면 저 는 모델 을 해당 하 는 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(for fileName: String) -> T?{
        guard let jsonDict = cacheJson(for: fileName) as? [String: Any] else {return nil}
        return Mapper().map(JSON: jsonDict)
    }
    
    //   
    @discardableResult
    static func setCache(array: [BaseMappable], for fileName: String) -> Bool{
        return self.setCache(json: array.map({$0.toJSON()}), for: fileName)
    }
    
    //   
    static func cacheArray(for fileName: String) -> Array?{
        guard let jsonArray = cacheJson(for: fileName) as? [[String: Any]] else {return nil}
        return Mapper().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 프로 토 콜 을 따 르 는 대상 만 지원 합 니 다. 모델 은 모두 Object Mapper 로 해석 되 기 때 문 입 니 다.하지만 생각해 보 니 제한 이 너무 큰 것 같 아 제 이 슨 데이터 에 대한 캐 시 를 추가 했다.
문제.
그 중 에 문제 가 발생 했 습 니 다. 바로 이 함수 가 샌 드 박스 에서 데 이 터 를 추출 하 는 데 사 용 됩 니 다. 사용 할 때 데이터 의 유형 을 확인 해 야 합 니 다.
static func cache(for fileName: String) -> T?{ 
    guard let jsonDict = cacheJson(for: fileName) as? [String: Any] else  {return nil} 
    return Mapper().map(JSON: jsonDict) 
}

그러나 호출 할 때 컴 파일 러 는 항상 컴 파일 되 지 않 습 니 다. Cannot explicitly specialie a generic function 을 알려 줍 니 다.나중에 so 에서 검 사 를 한 후에 야 알 게 되 었 습 니 다. 범 형 함 수 를 사용 할 때 반환 값 이 관련 유형 이 라면 성명 을 표시 해 야 합 니 다.
let a:Art = CacheManager.cache(for: "cacheName")

배 움 에 약 하 다 ~ ~ (⊙ ⊙ ⊙) b 코드 가 많 지 않 으 면 github 를 넣 지 않 는 다.

좋은 웹페이지 즐겨찾기