RealmStorage
Realm 数据库的现代包装器 [iOS, macOS, tvOS & watchOS]
快速使用
一个轻松编写代码的方式,强类型查询,快速开发数据层,多线程等更多有趣的功能。
let users = DB.user().objects { query in
query.add { $0.firstName.isEqual("Robert") }
.and { $0.events.count().isGreater(thanOrEqual: 5) }
.and(\.updatedAt.isNotNil)
}.get()
特性
RealmStorage
支持以下操作
- 模式自动生成
- 内置数据库迁移
- 多线程
- 强类型查询
- 写入事务
- 所有 CRUD 操作
如何使用
安装
要将RealmStorage
添加到基于Swift Package Manager的项目中,请添加以下内容
.package(url: "https://github.com/AndrewKochulab/RealmStorage.git")
Cocoapods
pod 'RealmStorage'
创建一个新的构建阶段 项目 -> 主目标 -> 构建阶段
,并添加以下代码
"$PODS_ROOT/Sourcery/bin/sourcery" --sources "$PODS_ROOT/RealmStorage/Sources/RealmStorage/PredicateFlow/Core/Classes/Utils/" --sources "$SRCROOT" --templates "$PODS_ROOT/RealmStorage/Sources/RealmStorage/PredicateFlow/Core/Templates/PredicateFlow.stencil" --output "$SRCROOT/PredicateFlow.generated.swift" --disableCache
将PredicateFlow.generated.swift
文件导入到主目标中。
它将自动生成所有用于获取数据库查询所需的模式(详细信息见下文)。
示例
创建表
import RealmSwift
import RealmStorage
final class User: IdentifiableStorageObject, PredicateSchema {
enum Gender: String {
case male, female
}
dynamic var createdAt = Date()
dynamic var updatedAt: Date?
dynamic var firstName = ""
dynamic var lastName = ""
private dynamic var genderName = ""
var gender: Gender? {
get { Gender(rawValue: genderName) }
set { genderName = newValue?.rawValue ?? "" }
}
let events = List<Event>()
}
final class Event: IdentifiableStorageObject, PredicateSchema {
dynamic var date: Date?
dynamic var name = ""
dynamic var author: User?
let members = List<EventMember>()
}
final class EventMember: IdentifiableStorageObject, PredicateSchema {
dynamic var joinedAt = Date()
dynamic var user: User? {
didSet {
updateCompoundID()
}
}
dynamic var event: Event? {
didSet {
updateCompoundID()
}
}
private func updateCompoundID() {
guard let user = user,
let event = event else {
return
}
self.id = CompoundID(
items: user.id.value, event.id.value,
separator: "_"
)
}
}
自动生成的模式代码看起来像
感谢 Andrea Del Fante 为 PredicateFlow 库所做的贡献。请见仓库:https://github.com/andreadelfante/PredicateFlow
/// The "User" Predicate Schema
internal struct UserSchema: GeneratedPredicateSchema {
internal var identifier: StringPredicateProperty { return builder.string("identifier") }
internal var createdAt: PredicateProperty<Date> { return builder.generic("createdAt") }
internal var updatedAt: PredicateProperty<Date> { return builder.generic("updatedAt") }
internal var firstName: StringPredicateProperty { return builder.string("firstName") }
internal var lastName: StringPredicateProperty { return builder.string("lastName") }
internal var genderName: StringPredicateProperty { return builder.string("genderName") }
internal var events: CollectionProperty<EventSchema> { return builder.collection("events") }
}
在事务中保存对象
let user = User().apply {
$0.id = Identifier(value: "user_id")
$0.firstName = "Steve"
$0.lastName = "Rogers"
$0.gender = .male
}
let event = Event().apply {
$0.id = Identifier(value: "event_id")
$0.name = "Avengers Game"
$0.date = Date().addingTimeInterval(3600 * 10)
$0.author = user
}
let eventMember = EventMember().apply {
$0.event = event
$0.user = user
}.apply {
event.members.append($0)
}
try DB.perform { transaction in
transaction.add(
objects: [user, event, eventMember],
update: false
)
}
在事务中更新对象
func update(user: User) throws {
try DB.user().update(user) {
$0.firstName = "Tony"
$0.lastName = "Stark"
}
}
func update(event: Event, newDate: Date) throws {
try DB.event().update(event) {
$0.date = newDate
}
}
同步抓取操作
let users = DB.user().objects { query in
query.add { $0.firstName.isEqual("Robert") }
.and { $0.events.count().isGreater(thanOrEqual: 5) }
.and(\.updatedAt.isNotNil)
}.get()
let user = DB.user().object(by: Identifier(value: "user_id"))
let lastEvent = DB.event().last()
let allEvents = DB.event().all().get()
异步抓取操作
DB.event().first { event in
if event != nil {
// do actions
}
}
DB.event().objects(matching: { query in
query.add { $0.members.count() > 1000 }
query.sort(by: { $0.date.ascending() })
}, completion: { operation in
let events = operation.get()
// do some actions
for event in events {
print(event.description)
}
})
创建自己的读取操作
final class ReadCurrentSubscriptionsDatabaseOperation: ReadObjectsDatabaseOperation<Subscription> {
init(shouldThreadSafe isThreadSafe: Bool = false) {
super.init(matching: { query in
query.add(\.hasExpired.isFalse)
query.sort(by: { $0.expiresAt.descending() })
}, shouldThreadSafe: isThreadSafe)
}
}
extension SubscriptionPersistence {
func current() -> [Subscription] {
ReadCurrentSubscriptionsDatabaseOperation().get()
}
}
let currentSubscriptions = DB.subscription().current()
// or
let currentSubscriptions = DB.subscription().objects(matching: { query in
query.add(\.hasExpired.isFalse)
query.sort(by: { $0.expiresAt.descending() })
}).get()
贡献
发现了一个错误、一个错别字或者某些没被很好地记录的细节吗?我们非常希望你能打开一个问题来告诉我我能改进什么!
欢迎贡献,并且我们非常感激!
许可证
本代码遵照MIT许可证分发。更多信息请查看LICENSE
文件。