Thanks to visit codestin.com
Credit goes to github.com

Skip to content

sarvex/AlecrimCoreData

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AlecrimCoreData

Language: Swift License: MIT CocoaPods Carthage compatible Forks Stars

AlecrimCoreData is a framework to easily access CoreData objects in Swift.

Minimum Requirements

  • Xcode 6.3
  • iOS 8.0 / OS X 10.10

Version History

  • 3.0 - Swift framework; WIP; added attributes support and other improvements
  • 2.1 - Swift framework; added CocoaPods and Carthage support
  • 2.0 - Swift framework; first public release as open source
  • 1.1 - Objective-C framework; private Alecrim team use
  • 1.0 - Objective-C framework; private Alecrim team use

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects.

CocoaPods 0.36 adds supports for Swift and embedded frameworks. You can install it with the following command:

$ gem install cocoapods

To integrate AlecrimCoreData into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!

pod 'AlecrimCoreData', '~> 3.0-beta.3'

Then, run the following command:

$ pod install

Carthage

Carthage is a decentralized dependency manager that automates the process of adding frameworks to your Cocoa application.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate AlecrimCoreData into your Xcode project using Carthage, specify it in your Cartfile:

github "Alecrim/AlecrimCoreData" >= 2.0

Manually

You can add AlecrimCoreData as a git submodule, drag the AlecrimCoreData.xcodeproj file into your Xcode project and add the framework product as an embedded binary in your application target.

Getting Started

Data Context

You can create a inherited class from AlecrimCoreData.Context and declare a property or method for each entity in your data context like the example below:

import AlecrimCoreData

let dataContext = DataContext()!

class DataContext: Context {
	var people:      Table<PersonEntity>     { return Table<PersonEntity>(context: self) }
	var departments: Table<DepartmentEntity> { return Table<DepartmentEntity>(context: self) }
}

It's important that properties (or methods) always return a new instance of a AlecrimCoreData.Table class.

Entities

It's assumed that all entity classes was already created and added to the project.

In the above section example, there are two entities: Person and Department (with Entity suffix added to their class names). You can name the entity classes as you like, of course.

Usage

Fetching

Basic Fetching

Say you have an Entity called Person, related to a Department (as seen in various Apple CoreData documentation [and MagicalRecord documentation too]). To get all of the Person entities as an array, use the following methods:

for person in dataContext.people {
	println(person.firstName)
}

You can also skip some results:

let people = dataContext.people.skip(3)

Or take only some results:

let people = dataContext.people.skip(3).take(7)

Or, to return the results sorted by a property:

let peopleSorted = dataContext.people.orderBy({ $0.lastName })

Or, to return the results sorted by multiple properties:

let peopleSorted = dataContext.people.orderBy({ $0.lastName }).thenBy({ $0.firstName })

// OR

let peopleSorted = dataContext.people.sortBy("lastName,firstName")

Or, to return the results sorted by multiple properties with different attributes:

let peopleSorted = dataContext.people.orderByDescending({ $0.lastName }).thenByAscending({ $0.firstName })

// OR

let peopleSorted = dataContext.people.sortBy("lastName:0,firstName:1")

// OR

let peopleSorted = dataContext.people.sortBy("lastName:0:[cd],firstName:1:[cd]")

If you have a unique way of retrieving a single object from your data store (such as via an identifier), you can use the following code:

if let person = dataContext.people.first({ $0.identifier == 123 }) {
	println(person.name)
}

Advanced Fetching

If you want to be more specific with your search, you can use filter predicates:

let itemsPerPage = 10  

for pageNumber in 0..<5 {
	println("Page: \(pageNumber)")
	
	let peopleInCurrentPage = dataContext.people
	    .filter({ $0.department << [dept1, dept2] })
	    .orderBy({ $0.firstName })
	    .thenBy({ $0.lastName })
	    .skip(pageNumber * itemsPerPage)
	    .take(itemsPerPage)
	
	for person in peopleInCurrentPage {
	    println("\(person.firstName) \(person.lastName) - \(person.department.name)")
	}
}

Asynchronous Fetching

You can also fetch entities asynchronously and get the results later on main thread:

let progress = dataContext.people.fetchAsync { fetchedEntities, error in
    if let entities = fetchedEntities {
        // ...
    }
}

Returning an Array

The data is actually fetched from Persistent Store only when toArray() is explicitly or implicitly called. So you can combine and chain other methods before this.

let peopleArray = dataContext.people.toArray()

// OR

let peopleArray = dataContext.people.sortBy("firstName,lastName").toArray()

// OR

let theSmiths = dataContext.people.filter({ $0.lastName == "Smith" }).orderBy({ $0.firstName })
let count = theSmiths.count()
let array = theSmiths.toArray()

// OR

for person in dataContext.people.sortBy("firstName,lastName") {
	// .toArray() is called implicitly when enumerating
}

Converting to other class types

Call the to... method in the end of chain.

let fetchRequest = dataContext.people.toFetchRequest()
let arrayController = dataContext.people.toArrayController() // OS X only
let fetchedResultsController = dataContext.people.toFetchedResultsController() // iOS only

Find the number of entities

You can also perform a count of the entities in your Persistent Store:

let count = dataContext.people.filter({ $0.lastName == "Smith" }).count()

Creating new Entities

When you need to create a new instance of an Entity, use:

let person = dataContext.people.createEntity()

You can also create or get first existing entity matching the criteria. If the entity does not exist, a new one is created and the specified attribute is assigned from the searched value automatically.

let person = dataContext.people.firstOrCreated({ $ 0.identifier == 123 })

Deleting Entities

To delete a single entity:

if let person = dataContext.people.first({ $0.identifier == 123 }) {
	dataContext.people.deleteEntity(person)
}

Saving

You can save the data context in the end, after all changes were made.

let person = dataContext.people.firstOrCreated({ $0.identifier == 9 })
person.firstName = "Christopher"
person.lastName = "Eccleston"
person.additionalInfo = "The best Doctor ever!"

// get success and error
let (success, error) = dataContext.save()

if success {
	// ...
}
else {
	println(error)
}

Threading

You can fetch and save entities in background calling a global function that creates a new data context instance for this:

// assuming that this department is saved and exists...
let department = dataContext.departments.first({ $0.identifier == 100 })!

// the closure below will run in a background context queue
performInBackground(dataContext) { backgroundDataContext in
	if let person = backgroundDataContext.people.first({ $0.identifier == 321 }) {
	    // must bring to backgroundDataContext
	    person.department = department.inContext(backgroundDataContext)! 
	    person.otherData = "Other Data"
	}
	
	backgroundDataContext.save()
}

Using attributes and closure parameters

Implementation, docs and tests are in progress at this moment. A code generator utility is in internal beta and will be available soon.

Branches and contribution

  • master - The production branch. Clone or fork this repository for the latest copy.
  • develop - The active development branch. Pull requests should be directed to this branch.

If you want to contribute, please feel free to fork the repository and send pull requests with your fixes, suggestions and additions. :-)

Inspired and based on


Contact

License

AlecrimCoreData is released under an MIT license. See LICENSE for more information.

About

A powerful and simple CoreData wrapper framework written in Swift.

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Swift 98.4%
  • Other 1.6%