GECoreDataManager 1.0.3

GECoreDataManager 1.0.3

Guillem Espejo维护。



  • 作者:
  • Guillem Espejo

一款简明现代的用于 iOS 的 Core Data 栈,用 Swift 编写。

Swift Version Build Status License Cocoapods Compatible Platform PRs Welcome

CoreDataManager 是一个旨在简化 Core Data 配置和使用的小型 Swift 框架。

它作为一个典型的基于 NSPersistentContainer 的 Core Data 栈来运作,提供对主和后台上下文访问。它还以同步/异步方式提供对 CRUD 操作的所有访问,并处理一些大多数用户都面临的常见线程陷阱。

特点

  • 直接访问主和后台 Core Data 上下文
  • 易用的 CRUD 方法
  • 支持基本多线程

要求

  • iOS 13.0+
  • Xcode 11.3

安装

CocoaPods

CocoaPods 是 Cocoa 项目的依赖管理器。有关使用和安装说明,请访问他们的网站。要使用 CocoaPods 将 CoreDataManager 集成到 Xcode 项目中,请将其在 Podfile 中指定。

pod 'GECoreDataManager'

设置

在开始使用CoreDataManager之前,您需要设置堆栈。这是通过调用异步的setup方法来完成的。您必须传递模型名称、堆栈类型和完成块作为参数。完成块将包含一个Result实例作为参数,这样您可以轻松知道是否发生了失败。

您可以通过调用其单例实例来访问CoreDataManager堆栈,然后在其上调用setup

import CoreDataManager
// Other imports ...

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let completionBlock = { (result: Result<Void,Error>) in
            switch result {
                case .success():
                    print("Core Data setup ended")
                  
                case .failure(let error):
                    print("Core Data setup error: \(error)")
            }
        }
        
        let stack = CoreDataManager.shared
        stack.setup(withModel:"Test", type: .inmemory ,completion: completionBlock )

        // ...
    }
}

CoreDataManager提供三种不同类型的基本堆栈,基于NSPersistentContainer类型。这些是:.standard.inmemory.binary。您通常会在大多数情况下使用.standard类型,并在编写单元测试时使用.inmemory

基本用法

CoreDataManager提供两种操作方式。第一种是一种传统方法,其中堆栈为您提供访问两个NSManagedObjectContext实例的方式。一个与主队列相关联,另一个与后台队列相关联。您必须正确使用它们。另一种方式是使用提供的CRUD操作方法。它们与直接使用上下文相比灵活性较低,但简化了操作,并处理了大多数人使用Core Data时面临的典型线程问题。

通过上下文使用

如果您通过直接上下文访问使用CoreDataManager,您有两个属性

  • mainContext
  • backgroundContext

这些上下文本质上是与其队列相关联的,所以任何使用它们的操作都必须考虑到这一点。

正如其名所示,mainContext与主队列相关联,必须始终在此队列中使用。通过此上下文检索的对象也将与该队列相关联。如果您尝试从任何其他线程访问其对象,它将崩溃。这是标准的Core Data行为,无法避免。

另一方面,backgroundContext将允许您从后台队列使用它并访问其对象。与主队列一样,上下文及其对象与后台队列相关联,因此从其他线程访问将导致崩溃。

通过CRUD操作使用

如果您使用CoreDataManager通过CRUD操作,通常会有两种方法:同步和异步。唯一的例外是,由于其自身的性质,没有异步更新。

根据方法,您可能需要提供一个代表您想要执行的操作的块,或者您需要提供一个NSFetchRequest。您将通过方法返回类型或通过完成块始终收到表示成功或失败的Result实例。

在示例项目中,您可以找到如何使用这些方法的示例。

CRUD示例

这些示例都从主线程调用。CoreDataManager将在执行方法的异步版本时自动在后台执行操作。如果异步操作有要返回的对象,它们将自动发送到主队列,如果需要,允许直接修改UI。

同步创建

// Creation block, TodoTask is an NSManagedObject subclass
let createBlock = { (context:NSManagedObjectContext) in
    let task = TodoTask(context: context)
    task.title = "To do task"
    task.done = false
}

// stack is already inited...
let result = stack.createObject(using:createBlock)

switch result {
    case .success:
        print("Created objects successfuly")
    
    case .failure(let error):
        print("Error creating: \(error.localizedDescription)")
}

异步创建

// Creation block, TodoTask is an NSManagedObject subclass
let createBlock = { (context:NSManagedObjectContext) in
    let task = TodoTask(context: context)
    task.title = "To do task"
    task.done = false
}

// Completion block, has a Result parameter
let completionBlock = { (result: Result<Void,Error>) in
    switch result {
        case .success:
            print("Created objects successfuly")
        
        case .failure(let error):
            print("Error creating: \(error.localizedDescription)")
    }
}

// stack is already inited...
stack.createObjectAsync(using:createBlock, completion: completionBlock)

同步获取

let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "TodoTask")
// stack is already inited...
let result = stack.fetchObject(using: fetchRequest)

switch result {
    case let .success(objects):
        let castedObjects = objects.map { (object) -> TodoTask in
            return object as! TodoTask
        }
        print(castedObjects)
    
    case .failure(let error):
        print("Error fetching: \(error.localizedDescription)")
}

异步抓取

let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "TodoTask")

let completionBlock = { (result : Result<[NSManagedObject],Error>) in
    switch result {
        case let .success(objects):
            let castedObjects = objects.map { (object) -> TodoTask in
                return object as! TodoTask
            }
            print(castedObjects)
        
        case .failure(let error):
            print("Error fetching: \(error.localizedDescription)")
    }
}

// stack is already inited...
stack.fetchObjectAsync(using: fetchRequest, completion: completionBlock)

同步更新

// TodoTask fetched anywhere...
let task = fetchedTasks.first!

let updateBlock = {
    task.done = true // Was false
}

// stack is already inited...
let updateResult = stack.updateObject(using: updateBlock)

switch updateResult {
    case .success:
        print("Updated objects successfuly")
    
    case .failure(let error):
        print("Error updating: \(error.localizedDescription)")
}

同步删除

let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "TodoTask")

// stack is already inited...
let result = stackManager.deleteObject(using: fetchRequest)

switch result {
    case .success(let deletedCount):
        print("Deleted \(deletedCount) 'Todo' tasks")
        
    case .failure(let error):
        print("Error updating: \(error.localizedDescription)")
}

异步删除

let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "TodoTask")

let completionBlock = { (result : Result<Int,Error>) in
    switch result {
        case let .success(deletedCount):
            print("Deleted \(deletedCount) 'Todo' tasks")
        
        case .failure(let error):
            print("Error updating: \(error.localizedDescription)")
    }
}

// stack is already inited...
stack.deleteObjectAsync(from: fetchRequest, completion: completionBlock)

示例

下载示例项目,查看如何使用CoreDataManager的CRUD操作。

贡献

如果您想为 CoreDataManager 贡献,请检查 LICENSE 文件以获取更多信息。

元数据

Guillem Espejo – [email protected]

基于MIT许可证发布。有关更多信息,请参阅

https://github.com/GuillemEspejo/github-link