restructured files, added way to transform section names in ManagedObjectListControllers

This commit is contained in:
John Rommel Estropia
2015-05-10 23:23:56 +09:00
parent a5be0fbf67
commit d481b93224
43 changed files with 522 additions and 529 deletions

View File

@@ -37,11 +37,11 @@ HardcoreData.beginAsynchronous { (transaction) -> Void in
Easy fetching:
```swift
let objects = HardcoreData.fetchAll(MyEntity)
let objects = HardcoreData.fetchAll(From(MyEntity))
```
```swift
let objects = HardcoreData.fetchAll(
MyEntity.self,
From(MyEntity),
Where("entityID", isEqualTo: 1),
SortedBy(.Ascending("entityID"), .Descending("name")),
CustomizeFetch { (fetchRequest) -> Void in
@@ -53,7 +53,7 @@ let objects = HardcoreData.fetchAll(
Simple queries:
```swift
let count = HardcoreData.queryValue(
MyEntity.self,
From(MyEntity),
Select<Int>(.Count("entityID"))
)
```
@@ -72,9 +72,11 @@ If you are already familiar with the inner workings of CoreData, here is a mappi
| `NSManagedObjectContext` | `BaseDataTransaction` subclasses<br />(`SynchronousDataTransaction`, `AsynchronousDataTransaction`, `DetachedDataTransaction`) |
RestKit and MagicalRecord set up their `NSManagedObjectContext`s this way:
<img src="https://cloud.githubusercontent.com/assets/3029684/6734049/40579660-ce99-11e4-9d38-829877386afb.png" alt="nested contexts" height=271 />
This ensures maximum data integrity between contexts without blocking the main queue. But as <a href="http://floriankugler.com/2013/04/29/concurrent-core-data-stack-performance-shootout/">Florian Kugler's investigation</a> found out, merging contexts is still by far faster than saving nested contexts. HardcoreData's `DataStack` takes the best of both worlds by treating the main `NSManagedObjectContext` as a read-only context, and only allows changes to be made within *transactions*:
<img src="https://cloud.githubusercontent.com/assets/3029684/6734050/4078b642-ce99-11e4-95ea-c0c1d24fbe80.png" alt="nested contexts and merge hybrid" height=212 />
This allows for a butter-smooth main thread, while still taking advantage of safe nested contexts.
@@ -82,19 +84,92 @@ This allows for a butter-smooth main thread, while still taking advantage of saf
## Setting up
The simplest way to initialize HardcoreData is to add a default store to the default stack:
```swift
HardcoreData.defaultStack.addSQLiteStore()
```
This one-liner does the following:
- Triggers the lazy-initialization of `HardcoreData.defaultStack` with a default `DataStack`
- Sets up the stack's `NSPersistentStoreCoordinator`, the root saving `NSManagedObjectContext`, and the read-only main `NSManagedObjectContext`
- Adds an automigrating SQLite store in the *"Application Support"* directory with the file name *"<App bundle name>.sqlite"*
- Creates and returns the `NSPersistentStore` instance on success, or an `NSError` on failure
For most cases this, confuguration is already appropriate. For more hardcore settings, here is a semi-complete example:
```swift
let dataStack = DataStack(modelName: "MyModel") // loads from the "MyModel.xcdatamodeld" file
switch dataStack.addInMemoryStore(configuration: "Config1") { // creates an in-memory store with entities from the "Config1" configuration in the .xcdatamodeld file
case .Success(let persistentStore): // persistentStore is an NSPersistentStore instance
println("Successfully created an in-memory store: \(persistentStore)"
case .Failure(let error): // error is an NSError instance
println("Failed creating an in-memory store with error: \(error.description)"
}
switch dataStack.addSQLiteStore(
fileURL: sqliteFileURL, // set the target file URL for the sqlite file
configuration: "Config2", // use entities from the "Config2" configuration in the .xcdatamodeld file
automigrating: true, // automatically run lightweight migrations or entity policy migrations when needed
resetStoreOnMigrationFailure: true) { // delete and recreate the sqlite file when migration conflicts occur (useful when debugging)
case .Success(let persistentStore): // persistentStore is an NSPersistentStore instance
println("Successfully created an sqlite store: \(persistentStore)"
case .Failure(let error): // error is an NSError instance
println("Failed creating an sqlite store with error: \(error.description)"
}
HardcoreData.defaultStack = dataStack // pass the dataStack to HardcoreData for easier access later on
```
Note that you dont need to do the `HardcoreData.defaultStack = dataStack` line. You can just as well hold a stack like this and call all methods directly from the `DataStack` instance:
```swift
class MyViewController: UIViewController {
let dataStack = DataStack(modelName: "MyModel")
override func viewDidLoad() {
super.viewDidLoad()
self.dataStack.addSQLiteStore()
}
func methodToBeCalledLaterOn() {
let objects = self.dataStack.fetchAll(From(MyEntity))
println(objects)
}
}
```
The difference is when you set the stack as the `HardcoreData.defaultStack`, you can call the stack's methods directly from `HardcoreData` itself:
```swift
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
HardcoreData.dataStack.addSQLiteStore()
}
func methodToBeCalledLaterOn() {
let objects = HardcoreData.fetchAll(From(MyEntity))
println(objects)
}
}
```
Check out the *HardcoreData.swift* and *DataStack.swift files* if you want to explore the inner workings of the data stack.
## Saving and processing transactions
(implemented; README pending)
## Fetching and querying
(implemented; README pending)
## Logging and error handling
(implemented; README pending)
## Observing changes and notifications (currently in the works)
## Observing changes and notifications
(implemented; README pending)
## Importing data
(currently implementing)