RealmSwift使用注意事项:
只要更改了模型的任意一个属性, 数据库版本号就必须增加, 不然就会崩溃,开发时稍微留心, 如果是上线那么有一种解决方案
- 因为上线必定会升级版本号, 所以App版本号可以作为数据库版本号
- 比如本次上线版本号是 1.2.0
- 那么我们需要把 1.2.0处理成 102000, 然后作为数据库的版本号
- 将1.2.0去掉'.', 成为一个字符串"120"
- 再给字符串的每一个字符后边添加一个"0"
- 转换成UIInt64类型, 作为数据库的版本号
- 当然如果你们的App版本号是类似这种: 1.2.345, 那么就需要给字符串长度不超过3位的后边添加两个"0", 变成: 100200345, 这个逻辑代码中会提供, 可以参考
- 创建数据库
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!)
}
}
- 封装单个模型的数据存储管理类
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) }
}
}
- 写模型
这里使用的是ObjectMapper 用于用户信息接口解析成模型
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"]
}
}
- 对应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
网友评论