Giter VIP home page Giter VIP logo

ezcoredata's Introduction

EZCoreData

Build Status Codacy Badge codecov Version License Platform

A library that builds up the basic main and private contexts for CoreData and brings a few utility methods

Table of Contents

Example Project

To run the example project, clone this repo, and run pod install from the Example directory first.

Installation

EZCoreData is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'EZCoreData'

Usage

Set-up

There aree basically 2 ways of initiating EZCoreData. The recommended one is using the EZCoreData.shared instance:

import EZCoreData

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Init Core Data
        EZCoreData.databaseName = "My_DB_Name"      // Initialize Core Data
        _ = EZCoreData.shared                       // Initialize Core Data
        return true
    }
...
}

Alternatively, you can save an instance of EZCoreData in a class of yours. AppDelegate, for instance:

import EZCoreData

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var ezCoreData: EZCoreData!

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Init Core Data
        ezCoreData = EZCoreData("My_DB_Namme") {
            // Handle completion
        }
        return true
    }
...
}

Count

Alright, now that your core data is setup, let's run a simple count method. Supposing you have a NSManagedObject child called Article, you can count doing the following:

let articleCount = Article.count()

Simple, right? BTW, you can pass a predicate here, so you count articles that conform to that predicate. For instance:

let articleCount = Article.count(NSPredicate(format: "title CONTAINS[c] 'Art'"))

Create & Save

let newArticle = Article.create()
newArticle?.id = Int.random(in: 0...400)
newArticle?.managedObjectContext?.saveContextToStore()

Get or Create

let newOrExistingArticle = Article.getOrCreate(attribute: "id", value: 2, context: context)
newOrExistingArticle.title = "EZCoreData lib was finally launched, and it looks great!"
newOrExistingArticle.save()

Read First

You can read the first object ay a given attribute:

let article = Article.readFirst(attribute: "id", value: "123")

Or you can pass through your preferred predicate:

let article = try Article.readFirst(NSPredicate(format: "id == 123"))

If you don't pass any predicate, the result will be the first Article in the CoreData.

Read All

Likewise, you can geta list of objects either passing attributes:

let articleList = Article.readAllByAttribute("title", value: "Art")

or predicates:

let predicate = NSPredicate(format: "title CONTAINS[c] '\(searchTerm)' or authors CONTAINS[c] '\(searchTerm)'")
Article.readAll(predicate: predicate)

Like the other read methods, if you don't pass any predicate, the result will be the full list of Articles:

let allArticles = Article.readAll()

Delete One

article.delete(context: context)

Delete All

You can Delete All by doing:

Article.deleteAll()

Or you can delete a subset:

let remainingList = Article.readAll(predicate: NSPredicate(format: "title CONTAINS[c] 'Art'"))
Article.deleteAll(except: remainingList, context: context)

Advanced Topics

ASYNC Methods

Since the examples below illustrate only the SYNC functions (without the part of the try-catch error handling), Let's illustrate at least one ASYNC method to count as an example :D:

Article.readFirst(attribute: "title", value: "Art") { (awesomeResult) in
    switch awesomeResult {
    case .success(result: let articlesList):
        print(articlesList!)                 // Do something with your list of articles
    case .failure(error: let error):
        print(error.localizedDescription)    // Handle your error
    }
}

Import JSON into Objects

Supose we have a JSON array or maybe a JSON object that you'd like to import to your CoreData. To do so, you first need to override the method open func populateFromJSON(_ json: [String: Any], context: NSManagedObjectContext) in your NSManagedObjectContext child class. Like we do in your example project:

import CoreData
import EZCoreData


public class Article: NSManagedObject {
    /// Populates Article objects from JSON
    public override func populateFromJSON(_ json: [String : Any], context: NSManagedObjectContext) {
        guard let rawId = json["id"]\ else { return }
        self.id = id
        self.title = json["title"] as? String

        guard let tags = json["tags"] as? [[String: Any]] else { return }
        do {
            guard let tagObjects = try Tag.importList(tags, idKey: "id", shouldSave: false, context: context) else { return }
            self.addToTags(NSSet(array: tagObjects))
        } catch let error {
            print(error.localizedDescription)
        }
    }
}

After overriding the method open func populateFromJSON(_ json: [String: Any], context: NSManagedObjectContext), you can import an object as simple as this:

let jsonObject: [String: Any] = [
    "id": 1,
    "title": "EZCoreData lib was finally launched, and it looks great!"
]
let article = importObject(jsonObject, shouldSave: true)

To import list of objects from a JSON, simply do this:

let jsonArray: [[String: Any]] = [
    [
        "id": 1,
        "title": "EZCoreData lib was finally launched, and it looks great!"
    ],
    [
        "id": 2,
        "title": "EZCoreData launch was delayed in 1 week"
    ],
]
let articlesList = Article.importList(jsonArray, idKey: "id", shouldSave: true)

You can check a sample code of this in this repo's example project.

Error Handling:

Most functions in thislibrary have 2 versions: Syncronous and Asyncronous. Theyhandle erros in a different form: Syncronous Functions: the SYNC functions throw the error so the user can handle it with a do+try+catch ou at least with a try? or try!. Asyncronous Functions: the ASYNC functions deal with the error internally and then return the result in a very civilized completion handler, hich derives from the following ENUM:

/// Handles any kind of results
public enum EZCoreDataResult<Object> {
    /// Handles success results
    case success(result: Object?)

    /// Handles failure results
    case failure(error: Error)
}

NSManagedObjectContext

Th library was designed to run the SYNC tasks in the main thread and the ASYNC tasks on the bacground task. For that reason, there are two built-in NSManagedObjectContexts in the shared instance:

  • EZCoreData.shared.mainThreadContext: Used in the lib for the SYNC methods. It's recommended to use the main context when the user is wasting his time waiting for a CoreData result.
  • EZCoreData.shared.privateThreadContext: Used in the lib for the ASYNC methods. It's recommended to use background/private contexts when you perform a time-consuming task or when your user doesn't need to waste his time waiting for the result.

There is also the possibility of using your own NSMAnagedObjectContext in the convenience methods. All methods have an optonal parameter context: NSManagedObjectContext that is filled with one of the default contexts if you don't specify them. It's important to say that th pre-set contexts should work fine and there is Unit Tests to guarante that.

Files' Reference:

  • EZCoreData: used for managing the instances of the project's NSPersistentContainer and NSManagedObjectContext
  • EZCoreDataLogger, used for holding the default ENUMs for LogLevel, Error and ResultCallback, as well as some convenient methods to manage logging (error, warning and info logging)
  • NSManagedObjectContext+Save: contains a convenience method (actually, sync and/or async versions of a method) for when you want to ensure the privateThreadContext saved changes will be propagated in its parent and siblings.
  • NSManagedObject+Create: a set of convenience methods for creating and saving an Object
  • NSManagedObject+Read: contains convenience methods to count objects and read list or single objects from the database
  • NSManagedObject+Update: used to import objects to the database. Included the method getOrCreate as well
  • NSManagedObject+Delete: used to delete a list of objects with the given characteristics, allowing the user to avoid deleting from a given list

Author

marcelosalloum, [email protected]

License

EZCoreData is available under the MIT license. See the LICENSE file for more info.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.