Skip to content
This repository has been archived by the owner on Feb 28, 2020. It is now read-only.

Commit

Permalink
Merge branch 'release/3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
vmartinelli committed May 21, 2015
2 parents 5a6110d + c95aee3 commit e579a13
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 128 deletions.
2 changes: 1 addition & 1 deletion AlecrimCoreData.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = "AlecrimCoreData"
s.version = "3.0-beta.8"
s.version = "3.0"
s.summary = "A framework to easily access Core Data objects in Swift."
s.homepage = "https://github.com/Alecrim/AlecrimCoreData"

Expand Down
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,11 @@ dataContext.entities.batchUpdate(["modified" : true, "dateModified" : NSDate()])

You can use `ContextOptions` class for a custom configuration.

#### App Extensions

See `Samples` folder for a configuration example for use in the main app and its extensions.


#### iCloud Core Data sync

See `Samples` folder for a configuration example for iCloud Core Data sync.
Expand Down Expand Up @@ -371,7 +376,7 @@ source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!

pod 'AlecrimCoreData', '~> 3.0-beta.8’
pod 'AlecrimCoreData', '~> 3.0'
```

Then, run the following command:
Expand Down Expand Up @@ -399,11 +404,11 @@ If you want to contribute, please feel free to fork the repository and send pull

### Version History

- 3.0 - Swift framework; added attributes support and many 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
- 3.0 - Swift framework: added attributes support and many 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

---

Expand Down
39 changes: 39 additions & 0 deletions Samples/AppExtensionDataContext.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// AppExtensionDataContext.swift
//
// Created by Vanderlei Martinelli on 2015-05-09.
//

import Foundation
import AlecrimCoreData

class AppExtensionDataContext: AlecrimCoreData.Context {

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

// MARK - custom init

convenience init?() {
let contextOptions = ContextOptions(stackType: .SQLite)

// only needed if entity class names are different from entity names
contextOptions.entityClassNameSuffix = "Entity"

// needed as your model probably is not in the main bundle
contextOptions.modelBundle = NSBundle(forClass: AppExtensionDataContext.self)

// set the managed object model name, usually the same name as the main app name
contextOptions.managedObjectModelName = "MyModelName"

// must be set to not infer from main bundle
contextOptions.persistentStoreRelativePath = "com.company.MyAppName/CoreData"

// the same identifier used to group your main app and its extensions
contextOptions.applicationGroupIdentifier = "group.com.company.MyAppName"

// call designated initializer
self.init(contextOptions: contextOptions)
}

}
12 changes: 6 additions & 6 deletions Samples/EnsemblesDataContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ class EnsemblesDataContext: AlecrimCoreData.Context {

// MARK - custom init

init?() {
convenience init?() {
let contextOptions = ContextOptions(stackType: .SQLite)

// only needed if model is not in main bundle
contextOptions.modelBundle = NSBundle(forClass: DataContext.self)

// only needed if entity class names are different from entity names
contextOptions.entityClassNameSuffix = "Entity"

// call super
super.init(contextOptions: contextOptions)
// only needed if model is not in main bundle
contextOptions.modelBundle = NSBundle(forClass: EnsemblesDataContext.self)

// call designated initializer
self.init(contextOptions: contextOptions)

// configure Ensembles
self.cloudFileSystem = CDEICloudFileSystem(ubiquityContainerIdentifier: "iCloud.com.company.MyApp")
Expand Down
18 changes: 9 additions & 9 deletions Samples/iCloudDataContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@ class iCloudDataContext: AlecrimCoreData.Context {

// MARK - custom init

init?() {
convenience init?() {
let contextOptions = ContextOptions(stackType: .SQLite)

// only needed if model is not in main bundle
contextOptions.modelBundle = NSBundle(forClass: DataContext.self)

// only needed if entity class names are different from entity names
contextOptions.entityClassNameSuffix = "Entity"

// only needed if model is not in main bundle
contextOptions.modelBundle = NSBundle(forClass: iCloudDataContext.self)

// only needed if the identifier is different from default identifier
contextOptions.ubiquitousContainerIdentifier = "iCloud.com.company.MyAppName"

// enable iCloud Core Data sync
contextOptions.ubiquityEnabled = true

// only needed if the identifier is different from default identifier
contextOptions.ubiquitousContainerIdentifier = "iCloud.com.company.MyApp"

// call super
super.init(contextOptions: contextOptions)
// call designated initializer
self.init(contextOptions: contextOptions)
}

}
112 changes: 58 additions & 54 deletions Source/AlecrimCoreData/Classes/Context.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,36 @@ import CoreData

public class Context {

private(set) internal var contextOptions: ContextOptions
private var stack: Stack!
private(set) public var managedObjectContext: NSManagedObjectContext! // The underlying managed object context
private let stack: Stack!
public let managedObjectContext: NSManagedObjectContext! // the underlying managed object context

private var ___background: Bool = false // background context machinery (you did not see it)

internal var contextOptions: ContextOptions { return self.stack.contextOptions }

public init?(contextOptions: ContextOptions? = nil) {
self.contextOptions = (contextOptions == nil ? ContextOptions() : contextOptions!)
public required init?(contextOptions: ContextOptions? = nil) {
let stackContextOptions = (contextOptions == nil ? ContextOptions() : contextOptions!)
stackContextOptions.fillEmptyOptions()

if self.contextOptions.filled {
// HAX: (vmartinelli) 2015-04-16 -> if filled == true, this constructor was called from the convenience init below and
// stack and managedObjectContext will be assigned there
self.stack = nil
self.managedObjectContext = nil
var stack = stackContextOptions.___stack
if stack == nil {
stack = Stack(contextOptions: stackContextOptions)
self.managedObjectContext = stack?.mainManagedObjectContext
}
else {
self.contextOptions.fillEmptyOptions()

if let stack = Stack(contextOptions: self.contextOptions) {
self.stack = stack
self.managedObjectContext = stack.mainManagedObjectContext
if stackContextOptions.___stackUsesNewBackgroundManagedObjectContext {
self.managedObjectContext = stack?.createBackgroundManagedObjectContext()
stackContextOptions.___stackUsesNewBackgroundManagedObjectContext = false
}
else {
self.stack = nil
self.managedObjectContext = nil

return nil
self.managedObjectContext = stack?.backgroundManagedObjectContext
}

self.___background = true
stackContextOptions.___stack = nil
}

self.stack = stack
}

public init?(rootManagedObjectContext: NSManagedObjectContext, mainManagedObjectContext: NSManagedObjectContext) {
Expand All @@ -52,10 +54,10 @@ public class Context {
}

if stackType != nil {
self.contextOptions = ContextOptions(stackType: stackType, managedObjectModelName: nil, storeOptions: store.options)
self.contextOptions.fillEmptyOptions(customConfiguration: true)
let stackContextOptions = ContextOptions(stackType: stackType, managedObjectModelName: nil, storeOptions: store.options)
stackContextOptions.fillEmptyOptions(customConfiguration: true)

if let stack = Stack(rootManagedObjectContext: rootManagedObjectContext, mainManagedObjectContext: mainManagedObjectContext, contextOptions: self.contextOptions) {
if let stack = Stack(rootManagedObjectContext: rootManagedObjectContext, mainManagedObjectContext: mainManagedObjectContext, contextOptions: stackContextOptions) {
self.stack = stack
self.managedObjectContext = stack.mainManagedObjectContext
}
Expand All @@ -67,38 +69,25 @@ public class Context {
}
}
else {
self.contextOptions = ContextOptions()
self.stack = nil
self.managedObjectContext = nil

return nil
}
}
else {
self.contextOptions = ContextOptions()
self.stack = nil
self.managedObjectContext = nil

return nil
}

}

// HAX: (vmartinelli) 2015-04-16 -> EXC_BAD_ACCESS if this contructor is not a convenience init
// and a property of inherited Context class is called
private convenience init?(parentContext: Context) {
self.init(contextOptions: parentContext.contextOptions)

self.contextOptions = parentContext.contextOptions
self.stack = parentContext.stack
self.managedObjectContext = parentContext.stack.createBackgroundManagedObjectContext()
}

}

extension Context {

public func save() -> (Bool, NSError?) {
public func save() -> (success: Bool, error: NSError?) {
return self.stack.saveManagedObjectContext(self.managedObjectContext)
}

Expand Down Expand Up @@ -173,9 +162,15 @@ extension Context {
internal func executeFetchRequest(fetchRequest: NSFetchRequest, error: NSErrorPointer) -> [AnyObject]? {
var objects: [AnyObject]?

self.performAndWait {
if self.___background {
// already in "performBlock"
objects = self.managedObjectContext.executeFetchRequest(fetchRequest, error: error)
}
else {
self.managedObjectContext.performBlockAndWait {
objects = self.managedObjectContext.executeFetchRequest(fetchRequest, error: error)
}
}

return objects
}
Expand Down Expand Up @@ -215,23 +210,21 @@ extension Context {
}

internal func executeBatchUpdateRequestWithEntityDescription(entityDescription: NSEntityDescription, propertiesToUpdate: [NSObject : AnyObject], predicate: NSPredicate, completionClosure: (Int, NSError?) -> Void) {
performInBackground(self) { backgroundContext in
let batchUpdateRequest = NSBatchUpdateRequest(entity: entityDescription)
batchUpdateRequest.propertiesToUpdate = propertiesToUpdate
batchUpdateRequest.predicate = predicate
batchUpdateRequest.resultType = .UpdatedObjectsCountResultType
let batchUpdateRequest = NSBatchUpdateRequest(entity: entityDescription)
batchUpdateRequest.propertiesToUpdate = propertiesToUpdate
batchUpdateRequest.predicate = predicate
batchUpdateRequest.resultType = .UpdatedObjectsCountResultType

let moc = self.stack.backgroundManagedObjectContext
moc.performBlock {
var error: NSError? = nil
let batchUpdateResult = moc.executeRequest(batchUpdateRequest, error: &error) as! NSBatchUpdateResult

let moc = backgroundContext.managedObjectContext
moc.performBlock {
var error: NSError? = nil
let batchUpdateResult = moc.executeRequest(batchUpdateRequest, error: &error) as! NSBatchUpdateResult

if error != nil {
completionClosure(0, error)
}
else {
completionClosure(batchUpdateResult.result as! Int, nil)
}
if error != nil {
completionClosure(0, error)
}
else {
completionClosure(batchUpdateResult.result as! Int, nil)
}
}
}
Expand All @@ -241,9 +234,20 @@ extension Context {
// MARK: - public global functions

public func performInBackground<T: Context>(parentContext: T, closure: (T) -> Void) {
let backgroundContext = T(parentContext: parentContext)!
performInBackground(parentContext, false, closure)
}

public func performInBackground<T: Context>(parentContext: T, createNewBackgroundManagedObjectContext: Bool, closure: (T) -> Void) {
parentContext.contextOptions.___stack = parentContext.stack
parentContext.contextOptions.___stackUsesNewBackgroundManagedObjectContext = createNewBackgroundManagedObjectContext
let backgroundContext = T(contextOptions: parentContext.contextOptions)!

backgroundContext.perform {
if !createNewBackgroundManagedObjectContext {
backgroundContext.managedObjectContext.reset()
}

closure(backgroundContext)
}
}

Loading

0 comments on commit e579a13

Please sign in to comment.