这是针对 CoreData 和 Realm 的 DAO 模式的实现。现在,您可以在应用程序中少考虑数据库。
特性
- 基于 Monreau 的数据库 CRUD 操作
- 数据库对象(模型)与应用对象(平铺)的抽象
支持的框架
- CoreData
- Realm
用法
import Monreau
import DAO
/// Create DAO instance
let dao = DAO(
storage: RealmStorage<UserModelObject>,
translator: UsersTranslator()
)
// Obtain messages (from backend for example)
let messages = messagesService.obtainMessages()
/// Save messages
try dao.persist(messages)
/// Obtain some info from database
let count = try dao.read().count
/// Erase all messages from database
try dao.erase()
它的工作原理
- 创建一些数据库模型类
// MARK: - DialogModelObject
final class DialogModelObject: RealmModel {
// MARK: - Properties
/// True if the dialog has been pinned
@objc dynamic var isPinned = false
/// All available (stored) the dialog's messages
let messages = List<MessageModelObject>()
}
// MARK: - MessageModelObject
final class MessageModelObject: RealmModel {
/// Sending date
@objc dynamic var date = Date()
/// Message text
@objc dynamic var text = ""
/// Receiver's id
@objc dynamic var receiverId = 0
/// Sender's id
@objc dynamic var senderId = 0
/// Message type
@objc dynamic var type = 0
/// True if the message is incoming
@objc dynamic var isIncoming = false
/// True if the message has been read
@objc dynamic var isRead = false
}
- 创建平铺对象类/结构体
import DAO
import Foundation
// MARK: - MessagePlainObject
struct MessagePlainObject: Plain {
// MARK: - Plain
var uniqueId: UniqueID {
return UniqueID(value: id)
}
// MARK: - Properties
/// Unique identifier
let id: Int
/// Sending date
let date: Date
/// Message text
let text: String
/// Sender's id
let senderId: Int
/// Receiver's id
let receiverId: Int
/// Message type
let type: Int
/// True if the message is incoming
let isIncoming: Bool
/// True if the message has been read
let isRead: Bool
}
// MARK: - DialogPlainObject
struct DialogPlainObject: Plain {
// MARK: - Plain
var uniqueId: UniqueID {
return UniqueID(value: id)
}
// MARK: - Properties
/// Unique id
let id: Int
/// True if the dialog has been pinned
let isPinned: Bool
/// All available (stored) the dialog's messages
let messages: [MessagePlainObject]
}
- 创建翻译器类
// MARK: - MessageTranslator
final class MessageTranslator {
// MARK: - Aliases
typealias PlainModel = MessagePlainObject
typealias DatabaseModel = MessageModelObject
}
// MARK: - Translator
extension MessageTranslator: Translator {
func translate(model: DatabaseModel) throws -> PlainModel {
MessagePlainObject(
id: Int(model.uniqueId) ?? 0,
date: model.date,
text: model.text,
senderId: model.senderId,
receiverId: model.receiverId,
type: model.type,
isIncoming: model.isIncoming,
isRead: model.isRead
)
}
func translate(plain: PlainModel) throws -> DatabaseModel {
let model = MessageModelObject()
try translate(from: plain, to: model)
return model
}
func translate(from plain: PlainModel, to databaseModel: DatabaseModel) throws {
if databaseModel.uniqueId.isEmpty {
databaseModel.uniqueId = plain.uniqueId.rawValue
}
databaseModel.date = plain.date
databaseModel.isIncoming = plain.isIncoming
databaseModel.isRead = plain.isRead
databaseModel.senderId = plain.senderId
databaseModel.text = plain.text
databaseModel.type = plain.type
databaseModel.receiverId = plain.receiverId
}
}
// MARK: - DialogTranslator
final class DialogTranslator {
// MARK: - Aliases
typealias PlainModel = DialogPlainObject
typealias DatabaseModel = DialogModelObject
}
// MARK: - Translator
extension DialogTranslator: Translator {
func translate(model: DatabaseModel) throws -> PlainModel {
DialogPlainObject(
id: Int(model.uniqueId) ?? 0,
isPinned: model.isPinned,
messages: try MessagesTranslator().translate(
models: Array(model.messages)
)
)
}
func translate(plain: PlainModel) throws -> DatabaseModel {
let model = DialogModelObject()
try translate(from: plain, to: model)
return model
}
func translate(from plain: PlainModel, to databaseModel: DatabaseModel) throws {
if databaseModel.uniqueId.isEmpty {
databaseModel.uniqueId = plain.uniqueId.rawValue
}
databaseModel.isPinned = plain.isPinned
databaseModel.messages.removeAll()
databaseModel.messages.append(
objectsIn: try MessagesTranslator().translate(
plains: plain.messages
)
)
}
}
- 使用它
let dao = DAO(
storage: RealmStorage<DialogModelObject>,
translator: DialogTranslator()
)
// Obtain messages (from backend for example)
let dialogs = dialogsService.obtainDialogs()
...
/// Obtain messages from your database
let dialogs = try dao.read()
需求
- iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+
- Xcode 9.0
- Swift 5
通讯
- 如果您发现了一个错误,请打开一个 issue。
- 如果您有功能请求,请打开一个 issue。
- 如果您想做出贡献,提交一个 pull request。
安装
CocoaPods
CocoaPods 是 Cocoa 项目的依赖管理器。您可以使用以下命令安装它:
$ gem install cocoapods
要使用 CocoaPods 将 DAO 集成到您的 Xcode 项目中,在您的 Podfile
中指定它
use_frameworks!
target "<Your Target Name>" do
pod "SwiftyDAO"
end
然后,运行以下命令
$ pod install
手动方式
如果您不希望使用任何依赖管理器,可以通过手动方式将 DAO 集成到项目中。
嵌入式框架
-
在终端中,使用
cd
命令进入您的顶级项目目录,如果您的项目尚未初始化为 git 仓库,则运行以下命令:$ git init
-
将 DAO 作为 git 子模块 加入,请运行以下命令:
$ git submodule add https://github.com/incetro/DAO.git
-
打开新的
DAO
文件夹,将DAO.xcodeproj
拖动到您应用的 Xcode 项目的项目导航器中。它应该位于您应用蓝色项目图标之下,位于所有其他 Xcode 组之上或之下都无关紧要。
-
在项目导航器中选中
DAO.xcodeproj
,并确认其部署目标与您应用目标的部署目标相匹配。 -
接下来,在项目导航器中(蓝色项目图标)选择您的应用项目,进入目标配置窗口,在侧边栏中选择“Targets”下的应用目标。
-
在该窗口顶部的标签栏中,打开“General”面板。
-
单击“Embedded Binaries”部分下的“+”按钮。
-
您将看到两个不同的
DAO.xcodeproj
文件夹,每个文件夹中都有一个DAO.framework
的两个不同版本,它们位于“Products”文件夹内。您从哪个“Products”文件夹选择都无关紧要,但您选择的
DAO.framework
的顶部或底部是重要的。 -
对于 iOS 选择顶部的
DAO.framework
,对于 OS X 选择底部的。您可以通过查看项目构建日志来验证您选择了哪个。对于
Nio
的构建目标将列示为DAO iOS
、DAO macOS
、DAO tvOS
或DAO watchOS
。 -
如此,就完成了!
DAO.framework
自动作为目标依赖项、链接框架和内嵌框架添加到复制文件构建阶段,这对于在模拟器和设备上构建所需的所有内容。
作者
incetro, [email protected]
许可证
DAO 发布在 MIT 许可证下。有关更多信息,请参阅 LICENSE 文件。