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-beta.8'
Browse files Browse the repository at this point in the history
  • Loading branch information
vmartinelli committed May 8, 2015
2 parents 21ebc7f + ada2247 commit 5a6110d
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 87 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.7"
s.version = "3.0-beta.8"
s.summary = "A framework to easily access Core Data objects in Swift."
s.homepage = "https://github.com/Alecrim/AlecrimCoreData"

Expand Down
47 changes: 18 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
[![Language: Swift](https://img.shields.io/badge/lang-Swift-orange.svg?style=flat)](https://developer.apple.com/swift/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://raw.githubusercontent.com/Alecrim/AlecrimCoreData/develop/LICENSE)
[![CocoaPods](https://img.shields.io/cocoapods/v/AlecrimCoreData.svg?style=flat)](http://cocoapods.org)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Forks](https://img.shields.io/github/forks/Alecrim/AlecrimCoreData.svg?style=flat)](https://github.com/Alecrim/AlecrimCoreData/network)
[![Stars](https://img.shields.io/github/stars/Alecrim/AlecrimCoreData.svg?style=flat)](https://github.com/Alecrim/AlecrimCoreData/stargazers)

Expand Down Expand Up @@ -75,7 +74,9 @@ let peopleSorted = dataContext.people.orderBy({ $0.lastName })
Or, to return the results sorted by multiple properties:

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

// OR

Expand All @@ -85,7 +86,9 @@ let peopleSorted = dataContext.people.sortBy("lastName,firstName")
Or, to return the results sorted by multiple properties with different attributes:

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

// OR

Expand Down Expand Up @@ -126,7 +129,7 @@ You can use aggregate functions on a single attribute:
let total = dataContext.entities.sum({ $0.value })
```

The `sum`, `min`, `max` and `average` functions are supported.
The `sum`, `min`, `max` and `average` functions are supported. If the original property is an `Optional` the result will be an `Optional` too.

#### Selecting Only Some Attributes

Expand Down Expand Up @@ -155,9 +158,9 @@ for pageNumber in 0..<5 {
println("Page: \(pageNumber)")

let peopleInCurrentPage = dataContext.people
.filter({ $0.department << [dept1, dept2] })
.orderBy({ $0.firstName })
.thenBy({ $0.lastName })
.filter { $0.department << [dept1, dept2] }
.orderBy { $0.firstName }
.thenBy { $0.lastName }
.skip(pageNumber * itemsPerPage)
.take(itemsPerPage)

Expand All @@ -172,7 +175,7 @@ for pageNumber in 0..<5 {
You can use collection operators for "to many" relationships:

```swift
let crowdedDepartments = dataContext.departments.filter({ $0.people.count > 100 })
let crowdedDepartments = dataContext.departments.filter { $0.people.count > 100 }
```

Only the `count` operator is supported in this version.
Expand All @@ -183,8 +186,8 @@ You can also fetch entities asynchronously and get the results later on main thr

```swift
let progress = dataContext.people.fetchAsync { fetchedEntities, error in
if let entities = fetchedEntities {
// ...
if error != nil {
// Do a nice error handling here
}
}
```
Expand All @@ -202,7 +205,10 @@ let peopleArray = dataContext.people.sortBy("firstName,lastName").toArray()

// OR

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

let count = theSmiths.count()
let array = theSmiths.toArray()

Expand Down Expand Up @@ -365,7 +371,7 @@ source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!

pod 'AlecrimCoreData', '~> 3.0-beta.7
pod 'AlecrimCoreData', '~> 3.0-beta.8
```
Then, run the following command:
Expand All @@ -374,23 +380,6 @@ 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](http://brew.sh/) using the following command:
```bash
$ brew update
$ brew install carthage
```
To integrate AlecrimCoreData into your Xcode project using Carthage, specify it in your `Cartfile`:
```ogdl
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.
Expand Down
43 changes: 43 additions & 0 deletions Source/AlecrimCoreData/Classes/Context.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,49 @@ public class Context {

}

public init?(rootManagedObjectContext: NSManagedObjectContext, mainManagedObjectContext: NSManagedObjectContext) {
if let coordinator = rootManagedObjectContext.persistentStoreCoordinator, let store = coordinator.persistentStores.first as? NSPersistentStore {
var stackType: StackType! = nil
if store.type == NSSQLiteStoreType {
stackType = .SQLite
}
else if store.type == NSInMemoryStoreType {
stackType = .InMemory
}

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

if let stack = Stack(rootManagedObjectContext: rootManagedObjectContext, mainManagedObjectContext: mainManagedObjectContext, contextOptions: self.contextOptions) {
self.stack = stack
self.managedObjectContext = stack.mainManagedObjectContext
}
else {
self.stack = nil
self.managedObjectContext = nil

return nil
}
}
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) {
Expand Down
102 changes: 64 additions & 38 deletions Source/AlecrimCoreData/Classes/ContextOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,55 @@ import Foundation
import CoreData

public final class ContextOptions {

private var cachedEntityNames = Dictionary<String, String>()

// MARK: - public static properties
public static var stringComparisonPredicateOptions = (NSComparisonPredicateOptions.CaseInsensitivePredicateOption | NSComparisonPredicateOptions.DiacriticInsensitivePredicateOption)


// MARK: - public properties - fetch request
public var fetchBatchSize = 20
public var entityClassNamePrefix: String? = nil
public var entityClassNameSuffix: String? = nil

// MARK: - public properties - entity class names x entity names
public var entityClassNamePrefix: String? = nil // you will have to change this if your class names begin with prefixes (for example: DMCustomer)
public var entityClassNameSuffix: String? = nil // you will have to change this if your class names have suffixes (for example: CustomerEntity)

// MARK: - public properties - stack options
public let stackType: StackType
public var configuration: String? = nil

public let mainBundle: NSBundle = NSBundle.mainBundle()
public var modelBundle: NSBundle = NSBundle.mainBundle()
// MARK: - public properties - store options
public var storeOptions: [NSObject : AnyObject]!
public var migratePersistentStoresAutomatically = true
public var inferMappingModelAutomaticallyOption = true

private(set) public var managedObjectModelURL: NSURL! = nil
private(set) public var managedObjectModel: NSManagedObjectModel! = nil
// MARK: - public properties - bundles
public let mainBundle: NSBundle = NSBundle.mainBundle()
public var modelBundle: NSBundle = NSBundle.mainBundle() // you will have to change this if your xcdatamodeld file is not in the main bundle (in a framework bundle, for example)

public var pesistentStoreRelativePath: String! = nil // defaults to main bundle identifier
public var pesistentStoreFileName: String! = nil // defaults to managed object model name + ".sqlite"
private(set) public var persistentStoreURL: NSURL! = nil
// MARK: - public properties - managed object model
public var managedObjectModelName: String! // defaults to main bundle name
public private(set) var managedObjectModelURL: NSURL! = nil
public private(set) var managedObjectModel: NSManagedObjectModel! = nil

public var configuration: String? = nil

public var ubiquityEnabled = false
// MARK: - public peroprties - app extensions
public var securityApplicationGroupIdentifier: String? // intented for app extensions use (com.apple.security.application-groups entitlement needed)

// MARK: - public properties - persistent location
public var persistentStoreRelativePath: String! = nil // defaults to main bundle identifier
public var persistentStoreFileName: String! = nil // defaults to managed object model name + ".sqlite"
public private(set) var persistentStoreURL: NSURL! = nil

// MARK: - public properties - iCloud
public var ubiquityEnabled = false // turns the iCloud "light" on/off
public var ubiquitousContainerIdentifier: String! // defaults to "iCloud." + main bundle identifier
public var ubiquitousContentName = "UbiquityStore"
public var ubiquitousContentRelativePath: String! = "CoreData/TransactionLogs"
private(set) public var ubiquitousContentURL: NSURL! = nil

public var migratePersistentStoresAutomatically = true
public var inferMappingModelAutomaticallyOption = true

public let stackType: StackType
public var managedObjectModelName: String! // defaults to main bundle name
public var storeOptions: [NSObject : AnyObject]!

private(set) internal var filled = false
public private(set) var ubiquitousContentURL: NSURL! = nil

// MARK: - private / internal properties
internal private(set) var filled = false
private var cachedEntityNames = Dictionary<String, String>()

// MARK: - init (finally)
public init(stackType: StackType = StackType.SQLite, managedObjectModelName: String? = nil, storeOptions: [NSObject : AnyObject]? = nil) {
self.stackType = stackType
self.managedObjectModelName = managedObjectModelName
Expand All @@ -56,19 +69,25 @@ public final class ContextOptions {

extension ContextOptions {

internal func fillEmptyOptions() {
internal func fillEmptyOptions(customConfiguration: Bool = false) {
//
if self.filled {
return
}

// verify if we have exiting managed object contexts set (customConfiguration == true in this case)
if customConfiguration {
self.filled = true
return
}

// if managed object model name is nil, try to get default name from main bundle
if self.managedObjectModelName == nil {
if let infoDictionary = self.mainBundle.infoDictionary {
self.managedObjectModelName = infoDictionary[kCFBundleNameKey] as? String
}
}

// managed object model
if self.managedObjectModelName != nil {
self.managedObjectModelURL = self.modelBundle.URLForResource(self.managedObjectModelName!, withExtension: "momd")
Expand All @@ -80,24 +99,31 @@ extension ContextOptions {

// local store
if let bundleIdentifier = self.mainBundle.bundleIdentifier {
if self.pesistentStoreRelativePath == nil {
self.pesistentStoreRelativePath = bundleIdentifier
if self.persistentStoreRelativePath == nil {
self.persistentStoreRelativePath = bundleIdentifier
}

let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask)
let persistentStoreContainerURL: NSURL?

if let securityApplicationGroupIdentifier = self.securityApplicationGroupIdentifier {
// stored in "~/Library/Group Containers/." (this method also creates the directory if it does not yet exist)
persistentStoreContainerURL = fileManager.containerURLForSecurityApplicationGroupIdentifier(securityApplicationGroupIdentifier)
} else{
let urls = fileManager.URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask)
persistentStoreContainerURL = urls.last as? NSURL
}

if let applicationSupportDirectoryURL = urls.last as? NSURL {
if self.pesistentStoreFileName == nil {
self.pesistentStoreFileName = self.managedObjectModelName.stringByAppendingPathExtension("sqlite")!
if let containerURL = persistentStoreContainerURL {
if self.persistentStoreFileName == nil {
self.persistentStoreFileName = self.managedObjectModelName.stringByAppendingPathExtension("sqlite")!
}

let pesistentStoreDirectoryURL = applicationSupportDirectoryURL.URLByAppendingPathComponent(self.pesistentStoreRelativePath, isDirectory: true)
self.persistentStoreURL = pesistentStoreDirectoryURL.URLByAppendingPathComponent(self.pesistentStoreFileName, isDirectory: false)
let persistentStoreDirectoryURL = containerURL.URLByAppendingPathComponent(self.persistentStoreRelativePath, isDirectory: true)
self.persistentStoreURL = persistentStoreDirectoryURL.URLByAppendingPathComponent(self.persistentStoreFileName, isDirectory: false)

let fileManager = NSFileManager.defaultManager()
if !fileManager.fileExistsAtPath(pesistentStoreDirectoryURL.path!) {
fileManager.createDirectoryAtURL(pesistentStoreDirectoryURL, withIntermediateDirectories: true, attributes: nil, error: nil)
if !fileManager.fileExistsAtPath(persistentStoreDirectoryURL.path!) {
fileManager.createDirectoryAtURL(persistentStoreDirectoryURL, withIntermediateDirectories: true, attributes: nil, error: nil)
}
}
}
Expand Down
Loading

0 comments on commit 5a6110d

Please sign in to comment.