StorageKit 0.3.1

StorageKit 0.3.1

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布最后发布2017年9月
SwiftSwift 版本3.2
SPM支持 SPM

Marco SantarossaEnnio Masi 维护。



  • StorageKit

StorageKit

您的数据存储故障排除工具🛠


StorageKit 是一个框架,它简化了管理持久层(如 Core Data、Realm)的复杂性。您可以通过高级接口轻松管理这些持久框架。

我们的使命是使持久层尽可能与客户端代码库分离。这样,您可以专注于开发应用程序。此外,您可以轻松迁移到另一个持久框架,保持相同的接口:StorageKit 会为您做几乎所有事情。

  • 无烦恼的设置👍
  • 易于使用🤖
  • 可扩展🚀
  • 支持后台查询 🙌🏼
  • 完全经过测试(嗯,几乎如此...)☺️ )

StorageKit 是一个与 Swift 3Xcode 8 兼容的项目。

目录

  1. 如何使用
  2. 定义实体
  3. CRUD
  4. 后台操作
  5. 安装
  6. 核心维护者
  7. 已知问题
  8. 待办事项
  9. 许可证
  10. 鸣谢

如何使用

第一步是创建一个新的 Storage 对象,指定特定类型(如 .CoreData.Realm),这是设置 StorageKit 的入口点对象

let storage = StorageKit.addStorage(type: .Realm)

或者

let storage = StorageKit.addStorage(type: .CoreData(dataModelName: "Example")

存储由一个 context 提供,这是您将使用的对象以执行常见的 CRUD 操作,例如

storage.mainContext?.fetch(predicate: NSPredicate(format: "done == false"), sortDescriptors: nil, completion: { (fetchedTasks: [RTodoTask]?) in
    self.tasks = fetchedTasks
        // do whatever you want
    }
)

或者

let task = functionThatRetrieveASpecificTaskFromDatabase()

do {
    try storage.mainContext?.delete(task)
} catch {
    // manage the error specific for CoreData or Realm
}

这就完成了!🎉

仅使用几行代码,您就能使用最喜欢的数据库(Storage)并通过 StorageContext 执行任何 CRUD 操作。

定义实体

两者 Core DataRealm 都依赖于两个基本对象来定义实体

Code Data Entity

import RealmSwift

class RTodoTask: Object {
    dynamic var name = ""
    dynamic var done = false
    
    override static func primaryKey() -> String? {
        return "taskID"
    }
}

StorageKit 无法定义您的实体类。这意味着您必须手动定义所有实体。这是您唯一必须自己做的事情,请稍等。

您可以使用以下方式创建一个新的实体

do {
    try let entity: MyEntity = context.create()
} catch {}

如果您使用 Realm,那么 entity 是一个未管理的对象,您应该明确地将它添加到数据库中

do {
    try storage.mainContext?.add(entity)
} catch {}

CRUD

C作为创建

do {
    try let entity: MyEntity = context.create()
} catch {}

此方法创建一个新实体对象:对于 Core Data 是一个 NSManagedObject,对于 Realm 是一个 Object

注意

在使用StorageKit之前,您必须自己创建一个类实体。因此,对于Core Data,您必须在数据模型中添加一个实体,对于Realm,您必须创建一个新的类,该类扩展了基类Object。如果您使用的是Realm配置,您在执行任何更新操作之前必须将其添加到存储中。

do {
    try let entity: MyEntity = context.create()
    entity.myProperty = "Hello"

    try context.add(entity)
} catch {}

读取时的R

    context.fetch(predicate: nil, sortDescriptors: nil) { (result: [MyEntity]?) in
        // do whatever you want with `result`
    }

更新时的U

do {
    try context.update {
        entity.myProperty = "Hello"
        entity2.myProperty = "Hello 2"
    }
} catch {}

注意

如果您使用的是Realm配置,您必须在执行任何更新操作之前使用add方法将实体添加到storage中。

删除时的D

do {
    try let entity: MyEntity = context.create()
    entity.myProperty = "Hello"

    try context.delete(entity)
} catch {}

后台操作

好消息!StorageKit已实施,重点在于后台操作和并发,以提高您应用的用户体验并简化您的生活。🎉

Storage(在GitHub上链接到一个类)公开以下方法

storage.performBackgroundTask {[weak self] (backgroundContext, backgroundQueue) in
    // the backgroundContext might be nil because of internal errors
    guard let backgroundContext = backgroundContext else { return }
    
    // perform your background CRUD operations here on the `backgroundContext`
    backgroundContext.fetch(predicate: nil, sortDescriptors: nil, completion: {[weak self] (entities: [MyEntity]?) in
    // do something with `entities`
    })
}

现在,重要的是entities是在后台上下文中检索的,所以如果您需要将这些实体用于另一个队列(例如在主队列中更新UI),您必须通过Storage公开的另一个方法将它们传递到另一个上下文中。

storage.getThreadSafeEntities(for: context, originalContext: backgroundContext, originalEntities: fetchedTasks, completion: { safeFetchedTaks in
    self?.tasks = safeFetchedTaks
                    
    DispatchQueue.main.async {
        dispatchGroup.leave()
    }
})

方法func getThreadSafeEntities<T: StorageEntityType>(for destinationContext: StorageContext, originalContext: StorageContext, originalEntities: [T], completion: @escaping ([T]) -> Void)创建一个与originalEntities具有相同数据的实体数组,但线程安全,可以在destinatinationContext中使用。

这意味着,一旦调用getThreadSafeEntities,您将能够在所选上下文中使用由completion: @escaping ([T]) -> Void)返回的实体。

此方法的常见用法:

  1. performBackgroundTask中执行后台操作(例如获取数据)
  2. 使用getThreadSafeEntities将检索到的实体移动到主上下文中
storage.performBackgroundTask {[weak self] (backgroundContext, backgroundQueue) in
    guard let backgroundContext = backgroundContext else { return }
    
    // 1
    backgroundContext.fetch(predicate: nil, sortDescriptors: nil, completion: {[weak self] (entities: [MyEntity]?) in
        // 2
        storage.getThreadSafeEntities(for: context, originalContext: backgroundContext, originalEntities: entities, completion: { safeEntities in
            self?.entities = safeEntities
        })
    })
}

核心维护者

守护者
Ennio Masi @ennioma
Marco Santarossa @MarcoSantaDev

已知问题

  • 现在无法排除安装Realm.frameworkRealmSwift.framework;
  • 示例项目中UI Test目标不起作用;

待办事项

  • 添加通用的错误接口
  • 如果不需要,请移除Realm依赖(用户可以在Core Data和Realm之间进行选择)
  • 添加响应式接口
  • 通过Swift Package Manager进行分发
  • 向上下文中添加更多功能
  • 添加通知

许可协议

StorageKit可在MIT许可下获取。有关更多信息,请参阅LICENSE文件。

致谢

图标由Nuon Project提供(LLuisa Iborra)。我们已更改盒子的颜色。