Big update. Migration tools in progress

This commit is contained in:
John Rommel Estropia
2015-07-01 08:03:09 +09:00
parent 71c80c3497
commit 40f22761bf
53 changed files with 2177 additions and 970 deletions

View File

@@ -34,63 +34,63 @@ public extension CoreStore {
// MARK: Public
/**
Using the `defaultStack`, creates a `ManagedObjectController` for the specified `NSManagedObject`. Multiple `ManagedObjectObserver`'s may then register themselves to be notified when changes are made to the `NSManagedObject`.
Using the `defaultStack`, creates a `ObjectMonitor` for the specified `NSManagedObject`. Multiple `ObjectObserver`s may then register themselves to be notified when changes are made to the `NSManagedObject`.
:param: object the `NSManagedObject` to observe changes from
:returns: a `ManagedObjectController` that monitors changes to `object`
:returns: a `ObjectMonitor` that monitors changes to `object`
*/
public static func observeObject<T: NSManagedObject>(object: T) -> ManagedObjectController<T> {
public static func monitorObject<T: NSManagedObject>(object: T) -> ObjectMonitor<T> {
return self.defaultStack.observeObject(object)
return self.defaultStack.monitorObject(object)
}
/**
Using the `defaultStack`, creates a `ManagedObjectListController` for a list of `NSManagedObject`'s that satisfy the specified fetch clauses. Multiple `ManagedObjectListObserver`'s may then register themselves to be notified when changes are made to the list.
Using the `defaultStack`, creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
:param: from a `From` clause indicating the entity type
:param: fetchClauses a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
:returns: a `ManagedObjectListController` instance that monitors changes to the list
:returns: a `ListMonitor` instance that monitors changes to the list
*/
public static func observeObjectList<T: NSManagedObject>(from: From<T>, _ groupBy: GroupBy? = nil, _ queryClauses: FetchClause...) -> ManagedObjectListController<T> {
public static func monitorList<T: NSManagedObject>(from: From<T>, _ groupBy: GroupBy? = nil, _ queryClauses: FetchClause...) -> ListMonitor<T> {
return self.defaultStack.observeObjectList(from, queryClauses)
return self.defaultStack.monitorList(from, queryClauses)
}
/**
Using the `defaultStack`, creates a `ManagedObjectListController` for a list of `NSManagedObject`'s that satisfy the specified fetch clauses. Multiple `ManagedObjectListObserver`'s may then register themselves to be notified when changes are made to the list.
Using the `defaultStack`, creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
:param: from a `From` clause indicating the entity type
:param: fetchClauses a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
:returns: a `ManagedObjectListController` instance that monitors changes to the list
:returns: a `ListMonitor` instance that monitors changes to the list
*/
public static func observeObjectList<T: NSManagedObject>(from: From<T>, _ groupBy: GroupBy? = nil, _ queryClauses: [FetchClause]) -> ManagedObjectListController<T> {
public static func monitorList<T: NSManagedObject>(from: From<T>, _ groupBy: GroupBy? = nil, _ queryClauses: [FetchClause]) -> ListMonitor<T> {
return self.defaultStack.observeObjectList(from, queryClauses)
return self.defaultStack.monitorList(from, queryClauses)
}
/**
Using the `defaultStack`, creates a `ManagedObjectListController` for a sectioned list of `NSManagedObject`'s that satisfy the specified fetch clauses. Multiple `ManagedObjectListObserver`'s may then register themselves to be notified when changes are made to the list.
Using the `defaultStack`, creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
:param: from a `From` clause indicating the entity type
:param: sectionedBy a `SectionedBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
:param: sectionBy a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
:param: fetchClauses a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
:returns: a `ManagedObjectListController` instance that monitors changes to the list
:returns: a `ListMonitor` instance that monitors changes to the list
*/
public static func observeSectionedList<T: NSManagedObject>(from: From<T>, _ sectionedBy: SectionedBy, _ fetchClauses: FetchClause...) -> ManagedObjectListController<T> {
public static func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
return self.defaultStack.observeSectionedList(from, sectionedBy, fetchClauses)
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
}
/**
Using the `defaultStack`, creates a `ManagedObjectListController` for a sectioned list of `NSManagedObject`'s that satisfy the specified fetch clauses. Multiple `ManagedObjectListObserver`'s may then register themselves to be notified when changes are made to the list.
Using the `defaultStack`, creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
:param: from a `From` clause indicating the entity type
:param: sectionedBy a `SectionedBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
:param: sectionBy a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
:param: fetchClauses a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
:returns: a `ManagedObjectListController` instance that monitors changes to the list
:returns: a `ListMonitor` instance that monitors changes to the list
*/
public static func observeSectionedList<T: NSManagedObject>(from: From<T>, _ sectionedBy: SectionedBy, _ fetchClauses: [FetchClause]) -> ManagedObjectListController<T> {
public static func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
return self.defaultStack.observeSectionedList(from, sectionedBy, fetchClauses)
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
}
}

View File

@@ -35,81 +35,81 @@ public extension DataStack {
// MARK: Public
/**
Creates a `ManagedObjectController` for the specified `NSManagedObject`. Multiple `ManagedObjectObserver`'s may then register themselves to be notified when changes are made to the `NSManagedObject`.
Creates a `ObjectMonitor` for the specified `NSManagedObject`. Multiple `ObjectObserver`s may then register themselves to be notified when changes are made to the `NSManagedObject`.
:param: object the `NSManagedObject` to observe changes from
:returns: a `ManagedObjectController` that monitors changes to `object`
:returns: a `ObjectMonitor` that monitors changes to `object`
*/
public func observeObject<T: NSManagedObject>(object: T) -> ManagedObjectController<T> {
public func monitorObject<T: NSManagedObject>(object: T) -> ObjectMonitor<T> {
CoreStore.assert(NSThread.isMainThread(), "Attempted to observe objects from \(typeName(self)) outside the main thread.")
return ManagedObjectController(
return ObjectMonitor(
dataStack: self,
object: object
)
}
/**
Creates a `ManagedObjectListController` for a list of `NSManagedObject`'s that satisfy the specified fetch clauses. Multiple `ManagedObjectListObserver`'s may then register themselves to be notified when changes are made to the list.
Creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
:param: from a `From` clause indicating the entity type
:param: fetchClauses a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
:returns: a `ManagedObjectListController` instance that monitors changes to the list
:returns: a `ListMonitor` instance that monitors changes to the list
*/
public func observeObjectList<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> ManagedObjectListController<T> {
public func monitorList<T: NSManagedObject>(from: From<T>, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
return self.observeObjectList(from, fetchClauses)
return self.monitorList(from, fetchClauses)
}
/**
Creates a `ManagedObjectListController` for a list of `NSManagedObject`'s that satisfy the specified fetch clauses. Multiple `ManagedObjectListObserver`'s may then register themselves to be notified when changes are made to the list.
Creates a `ListMonitor` for a list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
:param: from a `From` clause indicating the entity type
:param: fetchClauses a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
:returns: a `ManagedObjectListController` instance that monitors changes to the list
:returns: a `ListMonitor` instance that monitors changes to the list
*/
public func observeObjectList<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> ManagedObjectListController<T> {
public func monitorList<T: NSManagedObject>(from: From<T>, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
CoreStore.assert(NSThread.isMainThread(), "Attempted to observe objects from \(typeName(self)) outside the main thread.")
return ManagedObjectListController(
return ListMonitor(
dataStack: self,
from: from,
sectionedBy: nil,
sectionBy: nil,
fetchClauses: fetchClauses
)
}
/**
Creates a `ManagedObjectListController` for a sectioned list of `NSManagedObject`'s that satisfy the specified fetch clauses. Multiple `ManagedObjectListObserver`'s may then register themselves to be notified when changes are made to the list.
Creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
:param: from a `From` clause indicating the entity type
:param: sectionedBy a `SectionedBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
:param: sectionBy a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
:param: fetchClauses a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
:returns: a `ManagedObjectListController` instance that monitors changes to the list
:returns: a `ListMonitor` instance that monitors changes to the list
*/
public func observeSectionedList<T: NSManagedObject>(from: From<T>, _ sectionedBy: SectionedBy, _ fetchClauses: FetchClause...) -> ManagedObjectListController<T> {
public func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<T> {
return self.observeSectionedList(from, sectionedBy, fetchClauses)
return self.monitorSectionedList(from, sectionBy, fetchClauses)
}
/**
Creates a `ManagedObjectListController` for a sectioned list of `NSManagedObject`'s that satisfy the specified fetch clauses. Multiple `ManagedObjectListObserver`'s may then register themselves to be notified when changes are made to the list.
Creates a `ListMonitor` for a sectioned list of `NSManagedObject`s that satisfy the specified fetch clauses. Multiple `ListObserver`s may then register themselves to be notified when changes are made to the list.
:param: from a `From` clause indicating the entity type
:param: sectionedBy a `SectionedBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
:param: sectionBy a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
:param: fetchClauses a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
:returns: a `ManagedObjectListController` instance that monitors changes to the list
:returns: a `ListMonitor` instance that monitors changes to the list
*/
public func observeSectionedList<T: NSManagedObject>(from: From<T>, _ sectionedBy: SectionedBy, _ fetchClauses: [FetchClause]) -> ManagedObjectListController<T> {
public func monitorSectionedList<T: NSManagedObject>(from: From<T>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<T> {
CoreStore.assert(NSThread.isMainThread(), "Attempted to observe objects from \(typeName(self)) outside the main thread.")
return ManagedObjectListController(
return ListMonitor(
dataStack: self,
from: from,
sectionedBy: sectionedBy,
sectionBy: sectionBy,
fetchClauses: fetchClauses
)
}

View File

@@ -1,5 +1,5 @@
//
// ManagedObjectListController.swift
// ListMonitor.swift
// CoreStore
//
// Copyright (c) 2015 John Rommel Estropia
@@ -28,96 +28,51 @@ import CoreData
import GCDKit
// MARK: - SectionedBy
// MARK: - ListMonitor
/**
The `SectionedBy` clause indicates the key path to use to group the `ManagedObjectListController` objects into sections. An optional closure can also be provided to transform the value into an appropriate section name:
The `ListMonitor` monitors changes to a list of `NSManagedObject` instances. Observers that implement the `ListObserver` protocol may then register themselves to the `ListMonitor`'s `addObserver(_:)` method:
let listController = CoreStore.observeSectionedList(
From(MyPersonEntity),
SectionedBy("age") { "Age \($0)" },
OrderBy(.Ascending("lastName"))
)
*/
public struct SectionedBy {
// MARK: Public
/**
Initializes a `SectionedBy` clause with the key path to use to group `ManagedObjectListController` objects into sections
:param: sectionKeyPath the key path to use to group the objects into sections
*/
public init(_ sectionKeyPath: KeyPath) {
self.init(sectionKeyPath, { $0 })
}
/**
Initializes a `SectionedBy` clause with the key path to use to group `ManagedObjectListController` objects into sections, and a closure to transform the value for the key path to an appropriate section name
:param: sectionKeyPath the key path to use to group the objects into sections
:param: sectionIndexTransformer a closure to transform the value for the key path to an appropriate section name
*/
public init(_ sectionKeyPath: KeyPath, _ sectionIndexTransformer: (sectionName: String?) -> String?) {
self.sectionKeyPath = sectionKeyPath
self.sectionIndexTransformer = sectionIndexTransformer
}
// MARK: Internal
internal let sectionKeyPath: KeyPath
internal let sectionIndexTransformer: (sectionName: KeyPath?) -> String?
}
// MARK: - ManagedObjectListController
/**
The `ManagedObjectListController` monitors changes to a list of `NSManagedObject` instances. Observers that implement the `ManagedObjectListChangeObserver` protocol may then register themselves to the `ManagedObjectListController`'s `addObserver(_:)` method:
let listController = CoreStore.observeObjectList(
let monitor = CoreStore.monitorList(
From(MyPersonEntity),
Where("title", isEqualTo: "Engineer"),
OrderBy(.Ascending("lastName"))
)
listController.addObserver(self)
monitor.addObserver(self)
The `ManagedObjectListController` instance needs to be held on (retained) for as long as the list needs to be observed.
Observers registered via `addObserver(_:)` are not retained. `ManagedObjectListController` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles.
The `ListMonitor` instance needs to be held on (retained) for as long as the list needs to be observed.
Observers registered via `addObserver(_:)` are not retained. `ListMonitor` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles.
Lists created with `observeObjectList(...)` keep a single-section list of objects, where each object can be accessed by index:
Lists created with `monitorList(...)` keep a single-section list of objects, where each object can be accessed by index:
let firstPerson: MyPersonEntity = listController[0]
let firstPerson: MyPersonEntity = monitor[0]
Accessing the list with an index above the valid range will throw an exception.
Creating a sectioned-list is also possible with the `observeSectionedList(...)` method:
Creating a sectioned-list is also possible with the `monitorSectionedList(...)` method:
let listController = CoreStore.observeSectionedList(
let monitor = CoreStore.monitorSectionedList(
From(MyPersonEntity),
SectionedBy("age") { "Age \($0)" },
SectionBy("age") { "Age \($0)" },
Where("title", isEqualTo: "Engineer"),
OrderBy(.Ascending("lastName"))
)
listController.addObserver(self)
monitor.addObserver(self)
Objects from `ManagedObjectListController`'s created this way can be accessed either by an `NSIndexPath` or a tuple:
Objects from `ListMonitor`s created this way can be accessed either by an `NSIndexPath` or a tuple:
let indexPath = NSIndexPath(forItem: 3, inSection: 2)
let person1 = listController[indexPath]
let person2 = listController[2, 3]
let person1 = monitor[indexPath]
let person2 = monitor[2, 3]
In the example above, both `person1` and `person2` will contain the object at section=2, index=3.
*/
public final class ManagedObjectListController<T: NSManagedObject> {
public final class ListMonitor<T: NSManagedObject> {
// MARK: Public
/**
Accesses the object at the given index within the first section. This subscript indexer is typically used for `ManagedObjectListController`'s created with `addObserver(_:)`.
Accesses the object at the given index within the first section. This subscript indexer is typically used for `ListMonitor`s created with `addObserver(_:)`.
:param: index the index of the object. Using an index above the valid range will throw an exception.
*/
@@ -127,7 +82,7 @@ public final class ManagedObjectListController<T: NSManagedObject> {
}
/**
Accesses the object at the given `NSIndexPath`. This subscript indexer is typically used for `ManagedObjectListController`'s created with `observeSectionedList(_:)`.
Accesses the object at the given `NSIndexPath`. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`.
:param: indexPath the `NSIndexPath` for the object. Using an `indexPath` with an invalid range will throw an exception.
*/
@@ -137,7 +92,7 @@ public final class ManagedObjectListController<T: NSManagedObject> {
}
/**
Accesses the object at the given `sectionIndex` and `itemIndex`. This subscript indexer is typically used for `ManagedObjectListController`'s created with `observeSectionedList(_:)`.
Accesses the object at the given `sectionIndex` and `itemIndex`. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`.
:param: sectionIndex the section index for the object. Using a `sectionIndex` with an invalid range will throw an exception.
:param: itemIndex the index for the object within the section. Using an `itemIndex` with an invalid range will throw an exception.
@@ -176,17 +131,17 @@ public final class ManagedObjectListController<T: NSManagedObject> {
}
/**
Registers a `ManagedObjectListChangeObserver` 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.
To prevent retain-cycles, `ManagedObjectListController` only keeps `weak` references to its observers.
To prevent retain-cycles, `ListMonitor` only keeps `weak` references to its observers.
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ManagedObjectListController` unregisters previous notifications to the observer before re-registering them.
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ListMonitor` unregisters previous notifications to the observer before re-registering them.
:param: observer a `ManagedObjectListChangeObserver` to send change notifications to
:param: observer a `ListObserver` to send change notifications to
*/
public func addObserver<U: ManagedObjectListChangeObserver where U.EntityType == T>(observer: U) {
public func addObserver<U: ListObserver where U.EntityType == T>(observer: U) {
CoreStore.assert(NSThread.isMainThread(), "Attempted to add an observer of type \(typeName(observer)) outside the main thread.")
@@ -194,42 +149,42 @@ public final class ManagedObjectListController<T: NSManagedObject> {
self.registerChangeNotification(
&NotificationKey.willChangeList,
name: ManagedObjectListControllerWillChangeListNotification,
name: ListMonitorWillChangeListNotification,
toObserver: observer,
callback: { [weak observer] (listController) -> Void in
callback: { [weak observer] (monitor) -> Void in
if let observer = observer {
observer.managedObjectListWillChange(listController)
observer.listMonitorWillChange(monitor)
}
}
)
self.registerChangeNotification(
&NotificationKey.didChangeList,
name: ManagedObjectListControllerDidChangeListNotification,
name: ListMonitorDidChangeListNotification,
toObserver: observer,
callback: { [weak observer] (listController) -> Void in
callback: { [weak observer] (monitor) -> Void in
if let observer = observer {
observer.managedObjectListDidChange(listController)
observer.listMonitorDidChange(monitor)
}
}
)
}
/**
Registers a `ManagedObjectListObjectObserver` to be notified when changes to the receiver's list occur.
Registers a `ListObjectObserver` to be notified when changes to the receiver's list occur.
To prevent retain-cycles, `ManagedObjectListController` only keeps `weak` references to its observers.
To prevent retain-cycles, `ListMonitor` only keeps `weak` references to its observers.
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ManagedObjectListController` unregisters previous notifications to the observer before re-registering them.
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ListMonitor` unregisters previous notifications to the observer before re-registering them.
:param: observer a `ManagedObjectListObjectObserver` to send change notifications to
:param: observer a `ListObjectObserver` to send change notifications to
*/
public func addObserver<U: ManagedObjectListObjectObserver where U.EntityType == T>(observer: U) {
public func addObserver<U: ListObjectObserver where U.EntityType == T>(observer: U) {
CoreStore.assert(NSThread.isMainThread(), "Attempted to add an observer of type \(typeName(observer)) outside the main thread.")
@@ -237,39 +192,39 @@ public final class ManagedObjectListController<T: NSManagedObject> {
self.registerChangeNotification(
&NotificationKey.willChangeList,
name: ManagedObjectListControllerWillChangeListNotification,
name: ListMonitorWillChangeListNotification,
toObserver: observer,
callback: { [weak observer] (listController) -> Void in
callback: { [weak observer] (monitor) -> Void in
if let observer = observer {
observer.managedObjectListWillChange(listController)
observer.listMonitorWillChange(monitor)
}
}
)
self.registerChangeNotification(
&NotificationKey.didChangeList,
name: ManagedObjectListControllerDidChangeListNotification,
name: ListMonitorDidChangeListNotification,
toObserver: observer,
callback: { [weak observer] (listController) -> Void in
callback: { [weak observer] (monitor) -> Void in
if let observer = observer {
observer.managedObjectListDidChange(listController)
observer.listMonitorDidChange(monitor)
}
}
)
self.registerObjectNotification(
&NotificationKey.didInsertObject,
name: ManagedObjectListControllerDidInsertObjectNotification,
name: ListMonitorDidInsertObjectNotification,
toObserver: observer,
callback: { [weak observer] (listController, object, indexPath, newIndexPath) -> Void in
callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
if let observer = observer {
observer.managedObjectList(
listController,
observer.listMonitor(
monitor,
didInsertObject: object,
toIndexPath: newIndexPath!
)
@@ -278,14 +233,14 @@ public final class ManagedObjectListController<T: NSManagedObject> {
)
self.registerObjectNotification(
&NotificationKey.didDeleteObject,
name: ManagedObjectListControllerDidDeleteObjectNotification,
name: ListMonitorDidDeleteObjectNotification,
toObserver: observer,
callback: { [weak observer] (listController, object, indexPath, newIndexPath) -> Void in
callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
if let observer = observer {
observer.managedObjectList(
listController,
observer.listMonitor(
monitor,
didDeleteObject: object,
fromIndexPath: indexPath!
)
@@ -294,14 +249,14 @@ public final class ManagedObjectListController<T: NSManagedObject> {
)
self.registerObjectNotification(
&NotificationKey.didUpdateObject,
name: ManagedObjectListControllerDidUpdateObjectNotification,
name: ListMonitorDidUpdateObjectNotification,
toObserver: observer,
callback: { [weak observer] (listController, object, indexPath, newIndexPath) -> Void in
callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
if let observer = observer {
observer.managedObjectList(
listController,
observer.listMonitor(
monitor,
didUpdateObject: object,
atIndexPath: indexPath!
)
@@ -310,14 +265,14 @@ public final class ManagedObjectListController<T: NSManagedObject> {
)
self.registerObjectNotification(
&NotificationKey.didMoveObject,
name: ManagedObjectListControllerDidMoveObjectNotification,
name: ListMonitorDidMoveObjectNotification,
toObserver: observer,
callback: { [weak observer] (listController, object, indexPath, newIndexPath) -> Void in
callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
if let observer = observer {
observer.managedObjectList(
listController,
observer.listMonitor(
monitor,
didMoveObject: object,
fromIndexPath: indexPath!,
toIndexPath: newIndexPath!
@@ -328,17 +283,17 @@ public final class ManagedObjectListController<T: NSManagedObject> {
}
/**
Registers a `ManagedObjectListSectionObserver` to be notified when changes to the receiver's list occur.
Registers a `ListSectionObserver` to be notified when changes to the receiver's list occur.
To prevent retain-cycles, `ManagedObjectListController` only keeps `weak` references to its observers.
To prevent retain-cycles, `ListMonitor` only keeps `weak` references to its observers.
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ManagedObjectListController` unregisters previous notifications to the observer before re-registering them.
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ListMonitor` unregisters previous notifications to the observer before re-registering them.
:param: observer a `ManagedObjectListSectionObserver` to send change notifications to
:param: observer a `ListSectionObserver` to send change notifications to
*/
public func addObserver<U: ManagedObjectListSectionObserver where U.EntityType == T>(observer: U) {
public func addObserver<U: ListSectionObserver where U.EntityType == T>(observer: U) {
CoreStore.assert(NSThread.isMainThread(), "Attempted to add an observer of type \(typeName(observer)) outside the main thread.")
@@ -346,39 +301,39 @@ public final class ManagedObjectListController<T: NSManagedObject> {
self.registerChangeNotification(
&NotificationKey.willChangeList,
name: ManagedObjectListControllerWillChangeListNotification,
name: ListMonitorWillChangeListNotification,
toObserver: observer,
callback: { [weak observer] (listController) -> Void in
callback: { [weak observer] (monitor) -> Void in
if let observer = observer {
observer.managedObjectListWillChange(listController)
observer.listMonitorWillChange(monitor)
}
}
)
self.registerChangeNotification(
&NotificationKey.didChangeList,
name: ManagedObjectListControllerDidChangeListNotification,
name: ListMonitorDidChangeListNotification,
toObserver: observer,
callback: { [weak observer] (listController) -> Void in
callback: { [weak observer] (monitor) -> Void in
if let observer = observer {
observer.managedObjectListDidChange(listController)
observer.listMonitorDidChange(monitor)
}
}
)
self.registerObjectNotification(
&NotificationKey.didInsertObject,
name: ManagedObjectListControllerDidInsertObjectNotification,
name: ListMonitorDidInsertObjectNotification,
toObserver: observer,
callback: { [weak observer] (listController, object, indexPath, newIndexPath) -> Void in
callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
if let observer = observer {
observer.managedObjectList(
listController,
observer.listMonitor(
monitor,
didInsertObject: object,
toIndexPath: newIndexPath!
)
@@ -387,14 +342,14 @@ public final class ManagedObjectListController<T: NSManagedObject> {
)
self.registerObjectNotification(
&NotificationKey.didDeleteObject,
name: ManagedObjectListControllerDidDeleteObjectNotification,
name: ListMonitorDidDeleteObjectNotification,
toObserver: observer,
callback: { [weak observer] (listController, object, indexPath, newIndexPath) -> Void in
callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
if let observer = observer {
observer.managedObjectList(
listController,
observer.listMonitor(
monitor,
didDeleteObject: object,
fromIndexPath: indexPath!
)
@@ -403,14 +358,14 @@ public final class ManagedObjectListController<T: NSManagedObject> {
)
self.registerObjectNotification(
&NotificationKey.didUpdateObject,
name: ManagedObjectListControllerDidUpdateObjectNotification,
name: ListMonitorDidUpdateObjectNotification,
toObserver: observer,
callback: { [weak observer] (listController, object, indexPath, newIndexPath) -> Void in
callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
if let observer = observer {
observer.managedObjectList(
listController,
observer.listMonitor(
monitor,
didUpdateObject: object,
atIndexPath: indexPath!
)
@@ -419,14 +374,14 @@ public final class ManagedObjectListController<T: NSManagedObject> {
)
self.registerObjectNotification(
&NotificationKey.didMoveObject,
name: ManagedObjectListControllerDidMoveObjectNotification,
name: ListMonitorDidMoveObjectNotification,
toObserver: observer,
callback: { [weak observer] (listController, object, indexPath, newIndexPath) -> Void in
callback: { [weak observer] (monitor, object, indexPath, newIndexPath) -> Void in
if let observer = observer {
observer.managedObjectList(
listController,
observer.listMonitor(
monitor,
didMoveObject: object,
fromIndexPath: indexPath!,
toIndexPath: newIndexPath!
@@ -437,14 +392,14 @@ public final class ManagedObjectListController<T: NSManagedObject> {
self.registerSectionNotification(
&NotificationKey.didInsertSection,
name: ManagedObjectListControllerDidInsertSectionNotification,
name: ListMonitorDidInsertSectionNotification,
toObserver: observer,
callback: { [weak observer] (listController, sectionInfo, sectionIndex) -> Void in
callback: { [weak observer] (monitor, sectionInfo, sectionIndex) -> Void in
if let observer = observer {
observer.managedObjectList(
listController,
observer.listMonitor(
monitor,
didInsertSection: sectionInfo,
toSectionIndex: sectionIndex
)
@@ -453,14 +408,14 @@ public final class ManagedObjectListController<T: NSManagedObject> {
)
self.registerSectionNotification(
&NotificationKey.didDeleteSection,
name: ManagedObjectListControllerDidDeleteSectionNotification,
name: ListMonitorDidDeleteSectionNotification,
toObserver: observer,
callback: { [weak observer] (listController, sectionInfo, sectionIndex) -> Void in
callback: { [weak observer] (monitor, sectionInfo, sectionIndex) -> Void in
if let observer = observer {
observer.managedObjectList(
listController,
observer.listMonitor(
monitor,
didDeleteSection: sectionInfo,
fromSectionIndex: sectionIndex
)
@@ -470,13 +425,13 @@ public final class ManagedObjectListController<T: NSManagedObject> {
}
/**
Unregisters a `ManagedObjectListChangeObserver` from receiving notifications for changes to the receiver's list.
Unregisters a `ListObserver` from receiving notifications for changes to the receiver's list.
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
:param: observer a `ManagedObjectListChangeObserver` to unregister notifications to
:param: observer a `ListObserver` to unregister notifications to
*/
public func removeObserver<U: ManagedObjectListChangeObserver where U.EntityType == T>(observer: U) {
public func removeObserver<U: ListObserver where U.EntityType == T>(observer: U) {
CoreStore.assert(NSThread.isMainThread(), "Attempted to remove an observer of type \(typeName(observer)) outside the main thread.")
@@ -496,7 +451,7 @@ public final class ManagedObjectListController<T: NSManagedObject> {
// MARK: Internal
internal init(dataStack: DataStack, from: From<T>, sectionedBy: SectionedBy?, fetchClauses: [FetchClause]) {
internal init(dataStack: DataStack, from: From<T>, sectionBy: SectionBy?, fetchClauses: [FetchClause]) {
let context = dataStack.mainContext
@@ -514,7 +469,7 @@ public final class ManagedObjectListController<T: NSManagedObject> {
let fetchedResultsController = NSFetchedResultsController(
fetchRequest: fetchRequest,
managedObjectContext: context,
sectionNameKeyPath: sectionedBy?.sectionKeyPath,
sectionNameKeyPath: sectionBy?.sectionKeyPath,
cacheName: nil
)
@@ -524,7 +479,7 @@ public final class ManagedObjectListController<T: NSManagedObject> {
self.fetchedResultsControllerDelegate = fetchedResultsControllerDelegate
self.parentStack = dataStack
if let sectionIndexTransformer = sectionedBy?.sectionIndexTransformer {
if let sectionIndexTransformer = sectionBy?.sectionIndexTransformer {
self.sectionIndexTransformer = sectionIndexTransformer
}
@@ -554,7 +509,7 @@ public final class ManagedObjectListController<T: NSManagedObject> {
private let sectionIndexTransformer: (sectionName: KeyPath?) -> String?
private weak var parentStack: DataStack?
private func registerChangeNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (listController: ManagedObjectListController<T>) -> Void) {
private func registerChangeNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (monitor: ListMonitor<T>) -> Void) {
setAssociatedRetainedObject(
NotificationObserver(
@@ -564,7 +519,7 @@ public final class ManagedObjectListController<T: NSManagedObject> {
if let strongSelf = self {
callback(listController: strongSelf)
callback(monitor: strongSelf)
}
}
),
@@ -573,7 +528,7 @@ public final class ManagedObjectListController<T: NSManagedObject> {
)
}
private func registerObjectNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (listController: ManagedObjectListController<T>, object: T, indexPath: NSIndexPath?, newIndexPath: NSIndexPath?) -> Void) {
private func registerObjectNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (monitor: ListMonitor<T>, object: T, indexPath: NSIndexPath?, newIndexPath: NSIndexPath?) -> Void) {
setAssociatedRetainedObject(
NotificationObserver(
@@ -586,7 +541,7 @@ public final class ManagedObjectListController<T: NSManagedObject> {
let object = userInfo[UserInfoKeyObject] as? T {
callback(
listController: strongSelf,
monitor: strongSelf,
object: object,
indexPath: userInfo[UserInfoKeyIndexPath] as? NSIndexPath,
newIndexPath: userInfo[UserInfoKeyNewIndexPath] as? NSIndexPath
@@ -599,7 +554,7 @@ public final class ManagedObjectListController<T: NSManagedObject> {
)
}
private func registerSectionNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (listController: ManagedObjectListController<T>, sectionInfo: NSFetchedResultsSectionInfo, sectionIndex: Int) -> Void) {
private func registerSectionNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (monitor: ListMonitor<T>, sectionInfo: NSFetchedResultsSectionInfo, sectionIndex: Int) -> Void) {
setAssociatedRetainedObject(
NotificationObserver(
@@ -613,7 +568,7 @@ public final class ManagedObjectListController<T: NSManagedObject> {
let sectionIndex = (userInfo[UserInfoKeySectionIndex] as? NSNumber)?.integerValue {
callback(
listController: strongSelf,
monitor: strongSelf,
sectionInfo: sectionInfo,
sectionIndex: sectionIndex
)
@@ -627,9 +582,9 @@ public final class ManagedObjectListController<T: NSManagedObject> {
}
// MARK: - ManagedObjectListController: FetchedResultsControllerHandler
// MARK: - ListMonitor: FetchedResultsControllerHandler
extension ManagedObjectListController: FetchedResultsControllerHandler {
extension ListMonitor: FetchedResultsControllerHandler {
// MARK: FetchedResultsControllerHandler
@@ -639,7 +594,7 @@ extension ManagedObjectListController: FetchedResultsControllerHandler {
case .Insert:
NSNotificationCenter.defaultCenter().postNotificationName(
ManagedObjectListControllerDidInsertObjectNotification,
ListMonitorDidInsertObjectNotification,
object: self,
userInfo: [
UserInfoKeyObject: anObject,
@@ -649,7 +604,7 @@ extension ManagedObjectListController: FetchedResultsControllerHandler {
case .Delete:
NSNotificationCenter.defaultCenter().postNotificationName(
ManagedObjectListControllerDidDeleteObjectNotification,
ListMonitorDidDeleteObjectNotification,
object: self,
userInfo: [
UserInfoKeyObject: anObject,
@@ -659,7 +614,7 @@ extension ManagedObjectListController: FetchedResultsControllerHandler {
case .Update:
NSNotificationCenter.defaultCenter().postNotificationName(
ManagedObjectListControllerDidUpdateObjectNotification,
ListMonitorDidUpdateObjectNotification,
object: self,
userInfo: [
UserInfoKeyObject: anObject,
@@ -669,7 +624,7 @@ extension ManagedObjectListController: FetchedResultsControllerHandler {
case .Move:
NSNotificationCenter.defaultCenter().postNotificationName(
ManagedObjectListControllerDidMoveObjectNotification,
ListMonitorDidMoveObjectNotification,
object: self,
userInfo: [
UserInfoKeyObject: anObject,
@@ -686,7 +641,7 @@ extension ManagedObjectListController: FetchedResultsControllerHandler {
case .Insert:
NSNotificationCenter.defaultCenter().postNotificationName(
ManagedObjectListControllerDidInsertSectionNotification,
ListMonitorDidInsertSectionNotification,
object: self,
userInfo: [
UserInfoKeySectionInfo: sectionInfo,
@@ -696,7 +651,7 @@ extension ManagedObjectListController: FetchedResultsControllerHandler {
case .Delete:
NSNotificationCenter.defaultCenter().postNotificationName(
ManagedObjectListControllerDidDeleteSectionNotification,
ListMonitorDidDeleteSectionNotification,
object: self,
userInfo: [
UserInfoKeySectionInfo: sectionInfo,
@@ -712,7 +667,7 @@ extension ManagedObjectListController: FetchedResultsControllerHandler {
private func controllerWillChangeContent(controller: NSFetchedResultsController) {
NSNotificationCenter.defaultCenter().postNotificationName(
ManagedObjectListControllerWillChangeListNotification,
ListMonitorWillChangeListNotification,
object: self
)
}
@@ -720,7 +675,7 @@ extension ManagedObjectListController: FetchedResultsControllerHandler {
private func controllerDidChangeContent(controller: NSFetchedResultsController) {
NSNotificationCenter.defaultCenter().postNotificationName(
ManagedObjectListControllerDidChangeListNotification,
ListMonitorDidChangeListNotification,
object: self
)
}
@@ -799,16 +754,16 @@ private final class FetchedResultsControllerDelegate: NSFetchedResultsController
}
private let ManagedObjectListControllerWillChangeListNotification = "ManagedObjectListControllerWillChangeListNotification"
private let ManagedObjectListControllerDidChangeListNotification = "ManagedObjectListControllerDidChangeListNotification"
private let ListMonitorWillChangeListNotification = "ListMonitorWillChangeListNotification"
private let ListMonitorDidChangeListNotification = "ListMonitorDidChangeListNotification"
private let ManagedObjectListControllerDidInsertObjectNotification = "ManagedObjectListControllerDidInsertObjectNotification"
private let ManagedObjectListControllerDidDeleteObjectNotification = "ManagedObjectListControllerDidDeleteObjectNotification"
private let ManagedObjectListControllerDidUpdateObjectNotification = "ManagedObjectListControllerDidUpdateObjectNotification"
private let ManagedObjectListControllerDidMoveObjectNotification = "ManagedObjectListControllerDidMoveObjectNotification"
private let ListMonitorDidInsertObjectNotification = "ListMonitorDidInsertObjectNotification"
private let ListMonitorDidDeleteObjectNotification = "ListMonitorDidDeleteObjectNotification"
private let ListMonitorDidUpdateObjectNotification = "ListMonitorDidUpdateObjectNotification"
private let ListMonitorDidMoveObjectNotification = "ListMonitorDidMoveObjectNotification"
private let ManagedObjectListControllerDidInsertSectionNotification = "ManagedObjectListControllerDidInsertSectionNotification"
private let ManagedObjectListControllerDidDeleteSectionNotification = "ManagedObjectListControllerDidDeleteSectionNotification"
private let ListMonitorDidInsertSectionNotification = "ListMonitorDidInsertSectionNotification"
private let ListMonitorDidDeleteSectionNotification = "ListMonitorDidDeleteSectionNotification"
private let UserInfoKeyObject = "UserInfoKeyObject"
private let UserInfoKeyIndexPath = "UserInfoKeyIndexPath"

View File

@@ -0,0 +1,147 @@
//
// ListObserver.swift
// CoreStore
//
// Copyright (c) 2015 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import Foundation
import CoreData
// MARK: - ListObserver
/**
Implement the `ListObserver` protocol to observe changes to a list of `NSManagedObject`s. `ListObserver`s may register themselves to a `ListMonitor`'s `addObserver(_:)` method:
let monitor = CoreStore.monitorList(
From(MyPersonEntity),
OrderBy(.Ascending("lastName"))
)
monitor.addObserver(self)
*/
public protocol ListObserver: class {
/**
The `NSManagedObject` type for the observed list
*/
typealias EntityType: NSManagedObject
/**
Handles processing just before a change to the observed list occurs
:param: monitor the `ListMonitor` monitoring the list being observed
*/
func listMonitorWillChange(monitor: ListMonitor<EntityType>)
/**
Handles processing right after a change to the observed list occurs
:param: monitor the `ListMonitor` monitoring the object being observed
*/
func listMonitorDidChange(monitor: ListMonitor<EntityType>)
}
// MARK: - ListObjectObserver
/**
Implement the `ListObjectObserver` protocol to observe detailed changes to a list's object. `ListObjectObserver`s may register themselves to a `ListMonitor`'s `addObserver(_:)` method:
let monitor = CoreStore.monitorList(
From(MyPersonEntity),
OrderBy(.Ascending("lastName"))
)
monitor.addObserver(self)
*/
public protocol ListObjectObserver: ListObserver {
/**
Notifies that an object was inserted to the specified `NSIndexPath` in the list
:param: monitor the `ListMonitor` monitoring the list being observed
:param: object the entity type for the inserted object
:param: indexPath the new `NSIndexPath` for the inserted object
*/
func listMonitor(monitor: ListMonitor<EntityType>, didInsertObject object: EntityType, toIndexPath indexPath: NSIndexPath)
/**
Notifies that an object was deleted from the specified `NSIndexPath` in the list
:param: monitor the `ListMonitor` monitoring the list being observed
:param: object the entity type for the deleted object
:param: indexPath the `NSIndexPath` for the deleted object
*/
func listMonitor(monitor: ListMonitor<EntityType>, didDeleteObject object: EntityType, fromIndexPath indexPath: NSIndexPath)
/**
Notifies that an object at the specified `NSIndexPath` was updated
:param: monitor the `ListMonitor` monitoring the list being observed
:param: object the entity type for the updated object
:param: indexPath the `NSIndexPath` for the updated object
*/
func listMonitor(monitor: ListMonitor<EntityType>, didUpdateObject object: EntityType, atIndexPath indexPath: NSIndexPath)
/**
Notifies that an object's index changed
:param: monitor the `ListMonitor` monitoring the list being observed
:param: object the entity type for the moved object
:param: fromIndexPath the previous `NSIndexPath` for the moved object
:param: toIndexPath the new `NSIndexPath` for the moved object
*/
func listMonitor(monitor: ListMonitor<EntityType>, didMoveObject object: EntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
}
// MARK: - ListSectionObserver
/**
Implement the `ListSectionObserver` protocol to observe changes to a list's section info. `ListSectionObserver`s may register themselves to a `ListMonitor`'s `addObserver(_:)` method:
let monitor = CoreStore.monitorSectionedList(
From(MyPersonEntity),
SectionBy("age") { "Age \($0)" },
OrderBy(.Ascending("lastName"))
)
monitor.addObserver(self)
*/
public protocol ListSectionObserver: ListObjectObserver {
/**
Notifies that a section was inserted at the specified index
:param: monitor the `ListMonitor` monitoring the list being observed
:param: sectionInfo the `NSFetchedResultsSectionInfo` for the inserted section
:param: sectionIndex the new section index for the new section
*/
func listMonitor(monitor: ListMonitor<EntityType>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
/**
Notifies that a section was inserted at the specified index
:param: monitor the `ListMonitor` monitoring the list being observed
:param: sectionInfo the `NSFetchedResultsSectionInfo` for the deleted section
:param: sectionIndex the previous section index for the deleted section
*/
func listMonitor(monitor: ListMonitor<EntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
}

View File

@@ -1,147 +0,0 @@
//
// ManagedObjectListObserver.swift
// CoreStore
//
// Copyright (c) 2015 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import Foundation
import CoreData
// MARK: - ManagedObjectListChangeObserver
/**
Implement the `ManagedObjectListChangeObserver` protocol to observe changes to a list of `NSManagedObject`'s. `ManagedObjectListChangeObserver`'s may register themselves to a `ManagedObjectListController`'s `addObserver(_:)` method:
let listController = CoreStore.observeObjectList(
From(MyPersonEntity),
OrderBy(.Ascending("lastName"))
)
listController.addObserver(self)
*/
public protocol ManagedObjectListChangeObserver: class {
/**
The `NSManagedObject` type for the observed list
*/
typealias EntityType: NSManagedObject
/**
Handles processing just before a change to the observed list occurs
:param: listController the `ManagedObjectListController` monitoring the list being observed
*/
func managedObjectListWillChange(listController: ManagedObjectListController<EntityType>)
/**
Handles processing right after a change to the observed list occurs
:param: listController the `ManagedObjectListController` monitoring the object being observed
*/
func managedObjectListDidChange(listController: ManagedObjectListController<EntityType>)
}
// MARK: - ManagedObjectListObjectObserver
/**
Implement the `ManagedObjectListObjectObserver` protocol to observe detailed changes to a list's object. `ManagedObjectListObjectObserver`'s may register themselves to a `ManagedObjectListController`'s `addObserver(_:)` method:
let listController = CoreStore.observeObjectList(
From(MyPersonEntity),
OrderBy(.Ascending("lastName"))
)
listController.addObserver(self)
*/
public protocol ManagedObjectListObjectObserver: ManagedObjectListChangeObserver {
/**
Notifies that an object was inserted to the specified `NSIndexPath` in the list
:param: listController the `ManagedObjectListController` monitoring the list being observed
:param: object the entity type for the inserted object
:param: indexPath the new `NSIndexPath` for the inserted object
*/
func managedObjectList(listController: ManagedObjectListController<EntityType>, didInsertObject object: EntityType, toIndexPath indexPath: NSIndexPath)
/**
Notifies that an object was deleted from the specified `NSIndexPath` in the list
:param: listController the `ManagedObjectListController` monitoring the list being observed
:param: object the entity type for the deleted object
:param: indexPath the `NSIndexPath` for the deleted object
*/
func managedObjectList(listController: ManagedObjectListController<EntityType>, didDeleteObject object: EntityType, fromIndexPath indexPath: NSIndexPath)
/**
Notifies that an object at the specified `NSIndexPath` was updated
:param: listController the `ManagedObjectListController` monitoring the list being observed
:param: object the entity type for the updated object
:param: indexPath the `NSIndexPath` for the updated object
*/
func managedObjectList(listController: ManagedObjectListController<EntityType>, didUpdateObject object: EntityType, atIndexPath indexPath: NSIndexPath)
/**
Notifies that an object's index changed
:param: listController the `ManagedObjectListController` monitoring the list being observed
:param: object the entity type for the moved object
:param: fromIndexPath the previous `NSIndexPath` for the moved object
:param: toIndexPath the new `NSIndexPath` for the moved object
*/
func managedObjectList(listController: ManagedObjectListController<EntityType>, didMoveObject object: EntityType, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath)
}
// MARK: - ManagedObjectListSectionObserver
/**
Implement the `ManagedObjectListSectionObserver` protocol to observe changes to a list's section info. `ManagedObjectListSectionObserver`'s may register themselves to a `ManagedObjectListController`'s `addObserver(_:)` method:
let listController = CoreStore.observeSectionedList(
From(MyPersonEntity),
SectionedBy("age") { "Age \($0)" },
OrderBy(.Ascending("lastName"))
)
listController.addObserver(self)
*/
public protocol ManagedObjectListSectionObserver: ManagedObjectListObjectObserver {
/**
Notifies that a section was inserted at the specified index
:param: listController the `ManagedObjectListController` monitoring the list being observed
:param: sectionInfo the `NSFetchedResultsSectionInfo` for the inserted section
:param: sectionIndex the new section index for the new section
*/
func managedObjectList(listController: ManagedObjectListController<EntityType>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int)
/**
Notifies that a section was inserted at the specified index
:param: listController the `ManagedObjectListController` monitoring the list being observed
:param: sectionInfo the `NSFetchedResultsSectionInfo` for the deleted section
:param: sectionIndex the previous section index for the deleted section
*/
func managedObjectList(listController: ManagedObjectListController<EntityType>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int)
}

View File

@@ -1,5 +1,5 @@
//
// ManagedObjectController.swift
// ObjectMonitor.swift
// CoreStore
//
// Copyright (c) 2015 John Rommel Estropia
@@ -28,9 +28,9 @@ import CoreData
import GCDKit
private let ManagedObjectListControllerWillChangeObjectNotification = "ManagedObjectListControllerWillChangeObjectNotification"
private let ManagedObjectListControllerDidDeleteObjectNotification = "ManagedObjectListControllerDidDeleteObjectNotification"
private let ManagedObjectListControllerDidUpdateObjectNotification = "ManagedObjectListControllerDidUpdateObjectNotification"
private let ObjectMonitorWillChangeObjectNotification = "ObjectMonitorWillChangeObjectNotification"
private let ObjectMonitorDidDeleteObjectNotification = "ObjectMonitorDidDeleteObjectNotification"
private let ObjectMonitorDidUpdateObjectNotification = "ObjectMonitorDidUpdateObjectNotification"
private let UserInfoKeyObject = "UserInfoKeyObject"
@@ -42,19 +42,19 @@ private struct NotificationKey {
}
// MARK: - ManagedObjectController
// MARK: - ObjectMonitor
/**
The `ManagedObjectController` monitors changes to a single `NSManagedObject` instance. Observers that implement the `ManagedObjectObserver` protocol may then register themselves to the `ManagedObjectController`'s `addObserver(_:)` method:
The `ObjectMonitor` monitors changes to a single `NSManagedObject` instance. Observers that implement the `ObjectObserver` protocol may then register themselves to the `ObjectMonitor`'s `addObserver(_:)` method:
let objectController = CoreStore.observeObject(object)
objectController.addObserver(self)
let monitor = CoreStore.monitorObject(object)
monitor.addObserver(self)
The created `ManagedObjectController` instance needs to be held on (retained) for as long as the object needs to be observed.
The created `ObjectMonitor` instance needs to be held on (retained) for as long as the object needs to be observed.
Observers registered via `addObserver(_:)` are not retained. `ManagedObjectController` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles.
Observers registered via `addObserver(_:)` are not retained. `ObjectMonitor` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles.
*/
public final class ManagedObjectController<T: NSManagedObject> {
public final class ObjectMonitor<T: NSManagedObject> {
// MARK: Public
@@ -75,17 +75,17 @@ public final class ManagedObjectController<T: NSManagedObject> {
}
/**
Registers a `ManagedObjectObserver` to be notified when changes to the receiver's `object` are made.
Registers an `ObjectObserver` to be notified when changes to the receiver's `object` are made.
To prevent retain-cycles, `ManagedObjectController` only keeps `weak` references to its observers.
To prevent retain-cycles, `ObjectMonitor` only keeps `weak` references to its observers.
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ManagedObjectController` unregisters previous notifications to the observer before re-registering them.
Calling `addObserver(_:)` multiple times on the same observer is safe, as `ObjectMonitor` unregisters previous notifications to the observer before re-registering them.
:param: observer a `ManagedObjectObserver` to send change notifications to
:param: observer an `ObjectObserver` to send change notifications to
*/
public func addObserver<U: ManagedObjectObserver where U.EntityType == T>(observer: U) {
public func addObserver<U: ObjectObserver where U.EntityType == T>(observer: U) {
CoreStore.assert(NSThread.isMainThread(), "Attempted to add an observer of type \(typeName(observer)) outside the main thread.")
@@ -93,33 +93,33 @@ public final class ManagedObjectController<T: NSManagedObject> {
self.registerChangeNotification(
&NotificationKey.willChangeObject,
name: ManagedObjectListControllerWillChangeObjectNotification,
name: ObjectMonitorWillChangeObjectNotification,
toObserver: observer,
callback: { [weak self, weak observer] (objectController) -> Void in
callback: { [weak self, weak observer] (monitor) -> Void in
if let strongSelf = self, let object = strongSelf.object, let observer = observer {
observer.managedObjectWillUpdate(objectController, object: object)
observer.objectMonitor(monitor, willUpdateObject: object)
}
}
)
self.registerObjectNotification(
&NotificationKey.didDeleteObject,
name: ManagedObjectListControllerDidDeleteObjectNotification,
name: ObjectMonitorDidDeleteObjectNotification,
toObserver: observer,
callback: { [weak self, weak observer] (objectController, object) -> Void in
callback: { [weak self, weak observer] (monitor, object) -> Void in
if let strongSelf = self, let observer = observer {
observer.managedObjectWasDeleted(objectController, object: object)
observer.objectMonitor(monitor, didDeleteObject: object)
}
}
)
self.registerObjectNotification(
&NotificationKey.didUpdateObject,
name: ManagedObjectListControllerDidUpdateObjectNotification,
name: ObjectMonitorDidUpdateObjectNotification,
toObserver: observer,
callback: { [weak self, weak observer] (objectController, object) -> Void in
callback: { [weak self, weak observer] (monitor, object) -> Void in
if let strongSelf = self, let observer = observer {
@@ -136,9 +136,9 @@ public final class ManagedObjectController<T: NSManagedObject> {
}
strongSelf.lastCommittedAttributes = currentCommitedAttributes
observer.managedObjectWasUpdated(
objectController,
object: object,
observer.objectMonitor(
monitor,
didUpdateObject: object,
changedPersistentKeys: changedKeys
)
}
@@ -147,13 +147,13 @@ public final class ManagedObjectController<T: NSManagedObject> {
}
/**
Unregisters a `ManagedObjectObserver` from receiving notifications for changes to the receiver's `object`.
Unregisters an `ObjectObserver` from receiving notifications for changes to the receiver's `object`.
For thread safety, this method needs to be called from the main thread. An assertion failure will occur (on debug builds only) if called from any thread other than the main thread.
:param: observer a `ManagedObjectObserver` to unregister notifications to
:param: observer an `ObjectObserver` to unregister notifications to
*/
public func removeObserver<U: ManagedObjectObserver where U.EntityType == T>(observer: U) {
public func removeObserver<U: ObjectObserver where U.EntityType == T>(observer: U) {
CoreStore.assert(NSThread.isMainThread(), "Attempted to remove an observer of type \(typeName(observer)) outside the main thread.")
@@ -171,7 +171,8 @@ public final class ManagedObjectController<T: NSManagedObject> {
let context = dataStack.mainContext
let fetchRequest = NSFetchRequest()
fetchRequest.entity = context.entityDescriptionForEntityClass(T.self)
fetchRequest.entity = object.entity
fetchRequest.fetchLimit = 1
fetchRequest.resultType = .ManagedObjectResultType
fetchRequest.sortDescriptors = []
@@ -216,7 +217,7 @@ public final class ManagedObjectController<T: NSManagedObject> {
private var lastCommittedAttributes = [NSString: NSObject]()
private weak var parentStack: DataStack?
private func registerChangeNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (objectController: ManagedObjectController<T>) -> Void) {
private func registerChangeNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (monitor: ObjectMonitor<T>) -> Void) {
setAssociatedRetainedObject(
NotificationObserver(
@@ -226,7 +227,7 @@ public final class ManagedObjectController<T: NSManagedObject> {
if let strongSelf = self {
callback(objectController: strongSelf)
callback(monitor: strongSelf)
}
}
),
@@ -235,7 +236,7 @@ public final class ManagedObjectController<T: NSManagedObject> {
)
}
private func registerObjectNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (objectController: ManagedObjectController<T>, object: T) -> Void) {
private func registerObjectNotification(notificationKey: UnsafePointer<Void>, name: String, toObserver observer: AnyObject, callback: (monitor: ObjectMonitor<T>, object: T) -> Void) {
setAssociatedRetainedObject(
NotificationObserver(
@@ -248,7 +249,7 @@ public final class ManagedObjectController<T: NSManagedObject> {
let object = userInfo[UserInfoKeyObject] as? T {
callback(
objectController: strongSelf,
monitor: strongSelf,
object: object
)
}
@@ -261,9 +262,9 @@ public final class ManagedObjectController<T: NSManagedObject> {
}
// MARK: - ManagedObjectController: FetchedResultsControllerHandler
// MARK: - ObjectMonitor: FetchedResultsControllerHandler
extension ManagedObjectController: FetchedResultsControllerHandler {
extension ObjectMonitor: FetchedResultsControllerHandler {
// MARK: FetchedResultsControllerHandler
@@ -273,14 +274,14 @@ extension ManagedObjectController: FetchedResultsControllerHandler {
case .Delete:
NSNotificationCenter.defaultCenter().postNotificationName(
ManagedObjectListControllerDidDeleteObjectNotification,
ObjectMonitorDidDeleteObjectNotification,
object: self,
userInfo: [UserInfoKeyObject: anObject]
)
case .Update:
NSNotificationCenter.defaultCenter().postNotificationName(
ManagedObjectListControllerDidUpdateObjectNotification,
ObjectMonitorDidUpdateObjectNotification,
object: self,
userInfo: [UserInfoKeyObject: anObject]
)
@@ -293,7 +294,7 @@ extension ManagedObjectController: FetchedResultsControllerHandler {
private func controllerWillChangeContent(controller: NSFetchedResultsController) {
NSNotificationCenter.defaultCenter().postNotificationName(
ManagedObjectListControllerWillChangeObjectNotification,
ObjectMonitorWillChangeObjectNotification,
object: self
)
}

View File

@@ -1,5 +1,5 @@
//
// ManagedObjectObserver.swift
// ObjectObserver.swift
// CoreStore
//
// Copyright (c) 2015 John Rommel Estropia
@@ -27,15 +27,15 @@ import Foundation
import CoreData
// MARK: - ManagedObjectObserver
// MARK: - ObjectObserver
/**
Implement the `ManagedObjectObserver` protocol to observe changes to a single `NSManagedObject` instance. `ManagedObjectObserver`'s may register themselves to a `ManagedObjectController`'s `addObserver(_:)` method:
Implement the `ObjectObserver` protocol to observe changes to a single `NSManagedObject` instance. `ObjectObserver`s may register themselves to a `ObjectMonitor`'s `addObserver(_:)` method:
let objectController = CoreStore.observeObject(object)
objectController.addObserver(self)
let monitor = CoreStore.monitorObject(object)
monitor.addObserver(self)
*/
public protocol ManagedObjectObserver: class {
public protocol ObjectObserver: class {
/**
The `NSManagedObject` type for the observed object
@@ -45,25 +45,25 @@ public protocol ManagedObjectObserver: class {
/**
Handles processing just before a change to the observed `object` occurs
:param: objectController the `ManagedObjectController` monitoring the object being observed
:param: monitor the `ObjectMonitor` monitoring the object being observed
:param: object the `NSManagedObject` instance being observed
*/
func managedObjectWillUpdate(objectController: ManagedObjectController<EntityType>, object: EntityType)
func objectMonitor(monitor: ObjectMonitor<EntityType>, willUpdateObject object: EntityType)
/**
Handles processing right after a change to the observed `object` occurs
:param: objectController the `ManagedObjectController` monitoring the object being observed
:param: monitor the `ObjectMonitor` monitoring the object being observed
:param: object the `NSManagedObject` instance being observed
:param: changedPersistentKeys a `Set` of key paths for the attributes that were changed. Note that `changedPersistentKeys` only contains keys for attributes/relationships present in the persistent store, thus transient properties will not be reported.
*/
func managedObjectWasUpdated(objectController: ManagedObjectController<EntityType>, object: EntityType, changedPersistentKeys: Set<KeyPath>)
func objectMonitor(monitor: ObjectMonitor<EntityType>, didUpdateObject object: EntityType, changedPersistentKeys: Set<KeyPath>)
/**
Handles processing right after `object` is deleted
:param: objectController the `ManagedObjectController` monitoring the object being observed
:param: monitor the `ObjectMonitor` monitoring the object being observed
:param: object the `NSManagedObject` instance being observed
*/
func managedObjectWasDeleted(objectController: ManagedObjectController<EntityType>, object: EntityType)
func objectMonitor(monitor: ObjectMonitor<EntityType>, didDeleteObject object: EntityType)
}

View File

@@ -0,0 +1,72 @@
//
// SectionBy.swift
// CoreStore
//
// Copyright (c) 2015 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import Foundation
import CoreData
// MARK: - SectionBy
/**
The `SectionBy` clause indicates the key path to use to group the `ListMonitor` objects into sections. An optional closure can also be provided to transform the value into an appropriate section name:
let monitor = CoreStore.monitorSectionedList(
From(MyPersonEntity),
SectionBy("age") { "Age \($0)" },
OrderBy(.Ascending("lastName"))
)
*/
public struct SectionBy {
// MARK: Public
/**
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections
:param: sectionKeyPath the key path to use to group the objects into sections
*/
public init(_ sectionKeyPath: KeyPath) {
self.init(sectionKeyPath, { $0 })
}
/**
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
:param: sectionKeyPath the key path to use to group the objects into sections
:param: sectionIndexTransformer a closure to transform the value for the key path to an appropriate section name
*/
public init(_ sectionKeyPath: KeyPath, _ sectionIndexTransformer: (sectionName: String?) -> String?) {
self.sectionKeyPath = sectionKeyPath
self.sectionIndexTransformer = sectionIndexTransformer
}
// MARK: Internal
internal let sectionKeyPath: KeyPath
internal let sectionIndexTransformer: (sectionName: KeyPath?) -> String?
}