// // RelationStore.swift // QuickLocation // import Foundation import ObjectMapper import RxSwift import SwiftyUserDefaults struct RelationListResponse: BaseModelProtocol { var code: String? var message: String? var list: [RelationModel] = [] init?(map: Map) {} mutating func mapping(map: Map) { code <- (map["code"], kIntTransformStr) message <- map["message"] if message == nil { message <- map["msg"] } list <- map["data"] } } struct RelationModel: Mappable, Equatable { var name: String = "" var type: String = "" var limit: Int = -1 var icon: String = "" init?(map: Map) {} mutating func mapping(map: Map) { name <- map["name"] type <- (map["type"], kRelationTypeTransform) limit <- (map["limit"], kStrTransformInt) icon <- map["icon"] } var idx: String { type.trimmingCharacters(in: .whitespacesAndNewlines) } var showsHeart: Bool { idx == "1" } } private let kRelationTypeTransform = TransformOf(fromJSON: { value in transformStr(value) }, toJSON: { value in value }) private enum RelationStoreError: LocalizedError { case business(String) case empty var errorDescription: String? { switch self { case let .business(message): return message case .empty: return "关系列表为空" } } } final class RelationStore { static let shared = RelationStore() private(set) var list: [RelationModel] = [] private let disposeBag = DisposeBag() private init() { loadDisk() } func preload(completion: ((Result<[RelationModel], Error>) -> Void)? = nil) { UserService.relations() .subscribe(onNext: { [weak self] response in guard response.code == "0" else { completion?(.failure(RelationStoreError.business(response.message ?? "获取关系列表失败"))) return } guard !response.list.isEmpty else { completion?(.failure(RelationStoreError.empty)) return } self?.replace(response.list) completion?(.success(response.list)) }, onError: { error in completion?(.failure(error)) }) .disposed(by: disposeBag) } func item(for idx: String) -> RelationModel? { let key = idx.trimmingCharacters(in: .whitespacesAndNewlines) guard !key.isEmpty else { return nil } return list.first { $0.idx == key } } func name(for idx: String) -> String? { let name = item(for: idx)?.name.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" return name.isEmpty ? nil : name } func showsHeart(for idx: String) -> Bool { item(for: idx)?.showsHeart == true } private func replace(_ list: [RelationModel]) { self.list = list let json = list.map { $0.toJSON() } Defaults[\.userRelations] = try? JSONSerialization.data(withJSONObject: json) } private func loadDisk() { guard let data = Defaults[\.userRelations], let json = try? JSONSerialization.jsonObject(with: data) as? [[String: Any]] else { return } list = json.compactMap { RelationModel(JSON: $0) } } }