Swift 数据库 RealmSwift + ObjectMapper, 存单个对象

RealmSwift使用注意事项:

只要更改了模型的任意一个属性, 数据库版本号就必须增加, 不然就会崩溃,开发时稍微留心, 如果是上线那么有一种解决方案
  • 因为上线必定会升级版本号, 所以App版本号可以作为数据库版本号
  • 比如本次上线版本号是 1.2.0
  • 那么我们需要把 1.2.0处理成 102000, 然后作为数据库的版本号
  1. 将1.2.0去掉'.', 成为一个字符串"120"
  2. 再给字符串的每一个字符后边添加一个"0"
  3. 转换成UIInt64类型, 作为数据库的版本号
  • 当然如果你们的App版本号是类似这种: 1.2.345, 那么就需要给字符串长度不超过3位的后边添加两个"0", 变成: 100200345, 这个逻辑代码中会提供, 可以参考
1. 创建数据库
import RealmSwift

open class RealmManager: NSObject {
    public var realm: Realm!
    
    public override init() {
        do {
            realm = try Realm(name: "your_realm_name")
        } catch {
            print("open realm error = \(error.localizedDescription)")
        }
    }
    
    // 更新数据库版本
    // 只要数据模型有变动就必须升级数据库版本
    // 每次上线版本都会默认用最新的版本号作为数据库版本号, 例如: 1.2.0 对应数据库版本号: 102000
    static public func update(realmVersion: UInt64) {
        let config = Realm.Configuration(
            schemaVersion: realmVersion,
            migrationBlock: { migration, oldSchemaVersion in }
        )
        
        Realm.Configuration.defaultConfiguration = config
    }
}

extension Realm {

    public init(name: String) throws {
        // 找到沙盒路径 这里是Document
        let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory,
                                                          .userDomainMask,
                                                          true).first!
        // 拼接自己的路径
        let dbPath = docPath + "/db/" + name
        // 创建文件夹
        if !FileManager.default.fileExists(atPath: dbPath) {
            try FileManager.default.createDirectory(atPath: dbPath,
                                                withIntermediateDirectories: true,
                                                attributes: nil)
        }
        // 根据路径创建自己的realm文件URL
        let url = URL(string: dbPath + "/" + name + ".realm")
        try self.init(fileURL: url!)
    }
}
2. 封装单个模型的数据存储管理类
import Foundation
import RealmSwift

// 单个对象的存储
open class SingleObjectRealm<T: Object>: RealmManager {
    
    // 存储
    open func save(_ t: T) {
        delete()
        try? realm.write({ realm.add(t) })
    }
    
    // 获取
    open func value() -> T? {
        return realm.objects(T.self).first
    }
    
    // 删除
    open func delete() {
        try? realm.write({
            realm.delete(realm.objects(T.self))
        })
    }
    
    // 更新
    open func update(_ callback: (T) -> ()) {
        guard let t = value() else { return }
        try? realm.write{ callback(t)  }
    }
}
3. 写模型

这里使用的是ObjectMapper 用于用户信息接口解析成模型, 当然也可以单独创建模型, 只需要遵守 Object 协议

import Realm
import RealmSwift
import Foundation
import ObjectMapper

public class User: Object, Mappable {

    @Persisted public var name = ""
    @Persisted public var userId = 0
    @Persisted public var account = ""
    @Persisted public var headUrl = ""
    @Persisted public var birthday = ""
    
    required override init() { }
    
    required public init?(map: ObjectMapper.Map) { }

    public func mapping(map: ObjectMapper.Map) {
        name <- map["name"]
        userId <- map["userid"]
        account <- map["account"]
        headUrl <- map["head_url"]
        birthday <- map["birthday"]
    }
}
4. 对应User模型的存储处理类
import Foundation

public class UserManager: SingleObjectRealm<User> {
    public static let shared = UserManager()
    
    public var user: User?
    
    public var isLogin = false
    
    fileprivate override init() {
        super.init()
        user = value()
        isLogin = user != nil
    }
    
    public override func save(_ t: User) {
        super.save(t)
        user = t
        isLogin = true
    }
    
    public override func delete() {
        super.delete()
        user = nil
        isLogin = false
    }
    
    public override func value() -> User? {
        return super.value()
    }
}

使用:

  • 首先在程序的入口处理数据库版本号
    这个例子是类似于版本号是 1.2.0这种的
let info = Bundle.main.infoDictionary
if let versionStr = info?["CFBundleShortVersionString"] as? String {
    let vs = versionStr
        .split(separator: ".")
        .map { (version) -> Substring in
            var v = version
            if v.count == 1 { v.append("0") }
            return v
        }
        .joined()
    if let versionInt = UInt64(vs) {
        print("RealmVersion = \(versionInt)")
        RealmManager.update(realmVersion: versionInt)
    }
}
  • 一般用户信息是在接口返回之后存储, 或者更新
// 模拟服务端返回的用户数据
let userJson: [String: Any] = [
    "name": "空格格",
    "userid": "12345",
    "account": "18790737838",
    "birthday": "2022/7/17",
    "head_url": "https: www.xxx.com/user/head"]

// 转换成对象
if let user = Mapper<User>().map(JSON: userJson) {
    // 存储到数据库
    UserManager.shared.save(user)
}
print(NSHomeDirectory())
  • token失效等原因退出登录-删除User
UserManager.shared.delete()
  • 更新User中的某个字段值
UserManager.shared.update { (user) in
        user.name = "张三"
}

请点击代码详情: 示例demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,063评论 6 510
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,805评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,403评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,110评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,130评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,877评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,533评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,429评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,947评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,078评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,204评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,894评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,546评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,086评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,195评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,519评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,198评论 2 357