mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-04-10 19:26:51 +02:00
Merge branch 'develop' of https://github.com/JohnEstropia/CoreStore into develop
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = "CoreStore"
|
s.name = "CoreStore"
|
||||||
s.version = "1.1.2"
|
s.version = "1.2.1"
|
||||||
s.license = "MIT"
|
s.license = "MIT"
|
||||||
s.summary = "Simple, elegant, and smart Core Data programming with Swift"
|
s.summary = "Simple, elegant, and smart Core Data programming with Swift"
|
||||||
s.homepage = "https://github.com/JohnEstropia/CoreStore"
|
s.homepage = "https://github.com/JohnEstropia/CoreStore"
|
||||||
|
|||||||
@@ -31,16 +31,14 @@ public protocol ImportableObject: class {
|
|||||||
|
|
||||||
typealias ImportSource
|
typealias ImportSource
|
||||||
|
|
||||||
static func shouldImportFromSource(source: ImportSource) -> Bool
|
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
|
||||||
|
|
||||||
func didInsertFromImportSource(source: ImportSource) throws
|
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
|
||||||
|
|
||||||
func updateFromImportSource(source: ImportSource) throws
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension ImportableObject {
|
public extension ImportableObject {
|
||||||
|
|
||||||
static func shouldImportFromSource(source: ImportSource) -> Bool {
|
static func shouldInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -55,7 +53,25 @@ public protocol ImportableUniqueObject: ImportableObject {
|
|||||||
|
|
||||||
var uniqueIDValue: UniqueIDType { get set }
|
var uniqueIDValue: UniqueIDType { get set }
|
||||||
|
|
||||||
static func uniqueIDFromImportSource(source: ImportSource) throws -> UniqueIDType
|
static func uniqueIDFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws -> UniqueIDType?
|
||||||
|
|
||||||
|
static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool
|
||||||
|
|
||||||
|
func updateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public extension ImportableUniqueObject {
|
||||||
|
|
||||||
|
static func shouldUpdateFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) -> Bool {
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func didInsertFromImportSource(source: ImportSource, inTransaction transaction: BaseDataTransaction) throws {
|
||||||
|
|
||||||
|
try self.updateFromImportSource(source, inTransaction: transaction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -72,13 +88,13 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
return try autoreleasepool {
|
return try autoreleasepool {
|
||||||
|
|
||||||
if !T.shouldImportFromSource(source) {
|
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let object = self.create(into)
|
let object = self.create(into)
|
||||||
try object.didInsertFromImportSource(source)
|
try object.didInsertFromImportSource(source, inTransaction: self)
|
||||||
return object
|
return object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,10 +112,15 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
for source in sourceArray {
|
for source in sourceArray {
|
||||||
|
|
||||||
|
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
|
|
||||||
let object = self.create(into)
|
let object = self.create(into)
|
||||||
try object.didInsertFromImportSource(source)
|
try object.didInsertFromImportSource(source, inTransaction: self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,10 +141,15 @@ public extension BaseDataTransaction {
|
|||||||
var objects = [T]()
|
var objects = [T]()
|
||||||
for source in sourceArray {
|
for source in sourceArray {
|
||||||
|
|
||||||
|
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
|
|
||||||
let object = self.create(into)
|
let object = self.create(into)
|
||||||
try object.didInsertFromImportSource(source)
|
try object.didInsertFromImportSource(source, inTransaction: self)
|
||||||
|
|
||||||
objects.append(object)
|
objects.append(object)
|
||||||
}
|
}
|
||||||
@@ -143,24 +169,27 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
return try autoreleasepool {
|
return try autoreleasepool {
|
||||||
|
|
||||||
if !T.shouldImportFromSource(source) {
|
let uniqueIDKeyPath = T.uniqueIDKeyPath
|
||||||
|
guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let uniqueIDKeyPath = T.uniqueIDKeyPath
|
|
||||||
let uniqueIDValue = try T.uniqueIDFromImportSource(source)
|
|
||||||
|
|
||||||
if let object = self.fetchOne(From(T), Where(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
|
if let object = self.fetchOne(From(T), Where(uniqueIDKeyPath, isEqualTo: uniqueIDValue)) {
|
||||||
|
|
||||||
try object.updateFromImportSource(source)
|
try object.updateFromImportSource(source, inTransaction: self)
|
||||||
return object
|
return object
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
let object = self.create(into)
|
let object = self.create(into)
|
||||||
object.uniqueIDValue = uniqueIDValue
|
object.uniqueIDValue = uniqueIDValue
|
||||||
try object.didInsertFromImportSource(source)
|
try object.didInsertFromImportSource(source, inTransaction: self)
|
||||||
return object
|
return object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,7 +198,7 @@ public extension BaseDataTransaction {
|
|||||||
func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
||||||
into: Into<T>,
|
into: Into<T>,
|
||||||
sourceArray: [T.ImportSource],
|
sourceArray: [T.ImportSource],
|
||||||
preProcess: ((mapping: [T.UniqueIDType: T.ImportSource]) throws -> Void)? = nil) throws {
|
preProcess: ((inout mapping: [T.UniqueIDType: T.ImportSource]) throws -> Void)? = nil) throws {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
self.bypassesQueueing || self.transactionQueue.isCurrentExecutionContext(),
|
||||||
@@ -183,12 +212,11 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
|
|
||||||
if !T.shouldImportFromSource(source) {
|
guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let uniqueIDValue = try T.uniqueIDFromImportSource(source)
|
|
||||||
mapping[uniqueIDValue] = source
|
mapping[uniqueIDValue] = source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,7 +225,7 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
|
|
||||||
try preProcess(mapping: mapping)
|
try preProcess(mapping: &mapping)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +234,14 @@ public extension BaseDataTransaction {
|
|||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
|
|
||||||
let uniqueIDValue = object.uniqueIDValue
|
let uniqueIDValue = object.uniqueIDValue
|
||||||
try object.updateFromImportSource(mapping.removeValueForKey(uniqueIDValue)!)
|
|
||||||
|
guard let source = mapping.removeValueForKey(uniqueIDValue)
|
||||||
|
where T.shouldUpdateFromImportSource(source, inTransaction: self) else {
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try object.updateFromImportSource(source, inTransaction: self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,9 +249,14 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
|
|
||||||
|
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let object = self.create(into)
|
let object = self.create(into)
|
||||||
object.uniqueIDValue = uniqueIDValue
|
object.uniqueIDValue = uniqueIDValue
|
||||||
try object.didInsertFromImportSource(source)
|
try object.didInsertFromImportSource(source, inTransaction: self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,7 +265,7 @@ public extension BaseDataTransaction {
|
|||||||
func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
func importUniqueObjects<T where T: NSManagedObject, T: ImportableUniqueObject>(
|
||||||
into: Into<T>,
|
into: Into<T>,
|
||||||
sourceArray: [T.ImportSource],
|
sourceArray: [T.ImportSource],
|
||||||
preProcess: ((mapping: [T.UniqueIDType: T.ImportSource]) throws -> Void)? = nil,
|
preProcess: ((inout mapping: [T.UniqueIDType: T.ImportSource]) throws -> Void)? = nil,
|
||||||
postProcess: (sorted: [T]) -> Void) throws {
|
postProcess: (sorted: [T]) -> Void) throws {
|
||||||
|
|
||||||
CoreStore.assert(
|
CoreStore.assert(
|
||||||
@@ -241,12 +281,11 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
|
|
||||||
if !T.shouldImportFromSource(source) {
|
guard let uniqueIDValue = try T.uniqueIDFromImportSource(source, inTransaction: self) else {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let uniqueIDValue = try T.uniqueIDFromImportSource(source)
|
|
||||||
mapping[uniqueIDValue] = source
|
mapping[uniqueIDValue] = source
|
||||||
sortedIDs.append(uniqueIDValue)
|
sortedIDs.append(uniqueIDValue)
|
||||||
}
|
}
|
||||||
@@ -256,7 +295,7 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
|
|
||||||
try preProcess(mapping: mapping)
|
try preProcess(mapping: &mapping)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,7 +305,14 @@ public extension BaseDataTransaction {
|
|||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
|
|
||||||
let uniqueIDValue = object.uniqueIDValue
|
let uniqueIDValue = object.uniqueIDValue
|
||||||
try object.updateFromImportSource(mapping.removeValueForKey(uniqueIDValue)!)
|
|
||||||
|
guard let source = mapping.removeValueForKey(uniqueIDValue)
|
||||||
|
where T.shouldUpdateFromImportSource(source, inTransaction: self) else {
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try object.updateFromImportSource(source, inTransaction: self)
|
||||||
objects[uniqueIDValue] = object
|
objects[uniqueIDValue] = object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,9 +321,14 @@ public extension BaseDataTransaction {
|
|||||||
|
|
||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
|
|
||||||
|
guard T.shouldInsertFromImportSource(source, inTransaction: self) else {
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let object = self.create(into)
|
let object = self.create(into)
|
||||||
object.uniqueIDValue = uniqueIDValue
|
object.uniqueIDValue = uniqueIDValue
|
||||||
try object.didInsertFromImportSource(source)
|
try object.didInsertFromImportSource(source, inTransaction: self)
|
||||||
|
|
||||||
objects[uniqueIDValue] = object
|
objects[uniqueIDValue] = object
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>FMWK</string>
|
<string>FMWK</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.1.2</string>
|
<string>1.2.1</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ internal extension NSManagedObjectModel {
|
|||||||
return self.entityNameMapping[NSStringFromClass(entityClass)]!
|
return self.entityNameMapping[NSStringFromClass(entityClass)]!
|
||||||
}
|
}
|
||||||
|
|
||||||
@nonobjc internal func entityMapping() -> [String: NSManagedObject.Type] {
|
@nonobjc internal func entityTypesMapping() -> [String: NSManagedObject.Type] {
|
||||||
|
|
||||||
return self.entityNameMapping.reduce([:]) { (var mapping, pair) in
|
return self.entityNameMapping.reduce([:]) { (var mapping, pair) in
|
||||||
|
|
||||||
|
|||||||
@@ -273,6 +273,28 @@ public final class ListMonitor<T: NSManagedObject> {
|
|||||||
return sections[section]
|
return sections[section]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the index of the `NSManagedObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
|
||||||
|
|
||||||
|
- parameter object: the `NSManagedObject` to search the index of
|
||||||
|
- returns: the index of the `NSManagedObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
|
||||||
|
*/
|
||||||
|
public func indexOf(object: T) -> Int? {
|
||||||
|
|
||||||
|
return (self.fetchedResultsController.fetchedObjects as? [T] ?? []).indexOf(object)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the `NSIndexPath` of the `NSManagedObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
|
||||||
|
|
||||||
|
- parameter object: the `NSManagedObject` to search the index of
|
||||||
|
- returns: the `NSIndexPath` of the `NSManagedObject` if it exists in the `ListMonitor`'s fetched objects, or `nil` if not found.
|
||||||
|
*/
|
||||||
|
public func indexPathOf(object: T) -> NSIndexPath? {
|
||||||
|
|
||||||
|
return self.fetchedResultsController.indexPathForObject(object)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Registers a `ListObserver` to be notified when changes to the receiver's list occur.
|
Registers a `ListObserver` to be notified when changes to the receiver's list occur.
|
||||||
|
|
||||||
@@ -779,7 +801,7 @@ extension ListMonitor: FetchedResultsControllerHandler {
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
case .Move:
|
case .Move where indexPath != newIndexPath:
|
||||||
NSNotificationCenter.defaultCenter().postNotificationName(
|
NSNotificationCenter.defaultCenter().postNotificationName(
|
||||||
ListMonitorDidMoveObjectNotification,
|
ListMonitorDidMoveObjectNotification,
|
||||||
object: self,
|
object: self,
|
||||||
@@ -789,6 +811,9 @@ extension ListMonitor: FetchedResultsControllerHandler {
|
|||||||
UserInfoKeyNewIndexPath: newIndexPath!
|
UserInfoKeyNewIndexPath: newIndexPath!
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
default:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,13 +129,13 @@ public final class ObjectMonitor<T: NSManagedObject> {
|
|||||||
let previousCommitedAttributes = strongSelf.lastCommittedAttributes
|
let previousCommitedAttributes = strongSelf.lastCommittedAttributes
|
||||||
let currentCommitedAttributes = object.committedValuesForKeys(nil) as! [String: NSObject]
|
let currentCommitedAttributes = object.committedValuesForKeys(nil) as! [String: NSObject]
|
||||||
|
|
||||||
let changedKeys = currentCommitedAttributes.keys.reduce(Set<String>()) { (var changedKeys, key) -> Set<String> in
|
var changedKeys = Set<String>()
|
||||||
|
for key in currentCommitedAttributes.keys {
|
||||||
|
|
||||||
if previousCommitedAttributes[key] != currentCommitedAttributes[key] {
|
if previousCommitedAttributes[key] != currentCommitedAttributes[key] {
|
||||||
|
|
||||||
changedKeys.insert(key)
|
changedKeys.insert(key)
|
||||||
}
|
}
|
||||||
return changedKeys
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.lastCommittedAttributes = currentCommitedAttributes
|
strongSelf.lastCommittedAttributes = currentCommitedAttributes
|
||||||
@@ -179,7 +179,7 @@ public final class ObjectMonitor<T: NSManagedObject> {
|
|||||||
let fetchRequest = NSFetchRequest()
|
let fetchRequest = NSFetchRequest()
|
||||||
fetchRequest.entity = object.entity
|
fetchRequest.entity = object.entity
|
||||||
|
|
||||||
fetchRequest.fetchLimit = 1
|
fetchRequest.fetchLimit = 0
|
||||||
fetchRequest.resultType = .ManagedObjectResultType
|
fetchRequest.resultType = .ManagedObjectResultType
|
||||||
fetchRequest.sortDescriptors = []
|
fetchRequest.sortDescriptors = []
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ extension ObjectMonitor: FetchedResultsControllerHandler {
|
|||||||
userInfo: [UserInfoKeyObject: anObject]
|
userInfo: [UserInfoKeyObject: anObject]
|
||||||
)
|
)
|
||||||
|
|
||||||
case .Update:
|
case .Update, .Move where indexPath == newIndexPath:
|
||||||
NSNotificationCenter.defaultCenter().postNotificationName(
|
NSNotificationCenter.defaultCenter().postNotificationName(
|
||||||
ObjectMonitorDidUpdateObjectNotification,
|
ObjectMonitorDidUpdateObjectNotification,
|
||||||
object: self,
|
object: self,
|
||||||
|
|||||||
@@ -43,9 +43,17 @@ public extension CoreStore {
|
|||||||
/**
|
/**
|
||||||
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
Returns the entity name-to-class type mapping from the `defaultStack`'s model.
|
||||||
*/
|
*/
|
||||||
public static var entitiesByName: [String: NSManagedObject.Type] {
|
public static var entityTypesByName: [String: NSManagedObject.Type] {
|
||||||
|
|
||||||
return self.defaultStack.entitiesByName
|
return self.defaultStack.entityTypesByName
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass from `defaultStack`'s model.
|
||||||
|
*/
|
||||||
|
public static func entityDescriptionForType(type: NSManagedObject.Type) -> NSEntityDescription? {
|
||||||
|
|
||||||
|
return self.defaultStack.entityDescriptionForType(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -84,9 +84,20 @@ public final class DataStack {
|
|||||||
/**
|
/**
|
||||||
Returns the entity name-to-class type mapping from the `DataStack`'s model.
|
Returns the entity name-to-class type mapping from the `DataStack`'s model.
|
||||||
*/
|
*/
|
||||||
public var entitiesByName: [String: NSManagedObject.Type] {
|
public var entityTypesByName: [String: NSManagedObject.Type] {
|
||||||
|
|
||||||
return self.model.entityMapping()
|
return self.model.entityTypesMapping()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass.
|
||||||
|
*/
|
||||||
|
public func entityDescriptionForType(type: NSManagedObject.Type) -> NSEntityDescription? {
|
||||||
|
|
||||||
|
return NSEntityDescription.entityForName(
|
||||||
|
self.model.entityNameForClass(type),
|
||||||
|
inManagedObjectContext: self.mainContext
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -956,7 +956,7 @@ let person2 = self.monitor[1, 2]
|
|||||||
# Installation
|
# Installation
|
||||||
- Requires:
|
- Requires:
|
||||||
- iOS 8 SDK and above
|
- iOS 8 SDK and above
|
||||||
- Swift 2.0
|
- Swift 2.0 (XCode 7 beta 5)
|
||||||
- Dependencies:
|
- Dependencies:
|
||||||
- [GCDKit](https://github.com/JohnEstropia/GCDKit)
|
- [GCDKit](https://github.com/JohnEstropia/GCDKit)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user