# ListMonitor

    @available(OSX 10.12, *)
    public final class ListMonitor<D> : Hashable where D : DynamicObject

The `ListMonitor` monitors changes to a list of `DynamicObject` instances. Observers that implement the `ListObserver` protocol may then register themselves to the `ListMonitor`‘s `addObserver(_:)` method:

    let monitor = CoreStore.monitorList(
        From<Person>(),
        Where("title", isEqualTo: "Engineer"),
        OrderBy(.ascending("lastName"))
    )
    monitor.addObserver(self)

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 `monitorList(...)` keep a single-section list of objects, where each object can be accessed by index:

    let firstPerson: MyPersonEntity = monitor[0]

Accessing the list with an index above the valid range will raise an exception.

Creating a sectioned-list is also possible with the `monitorSectionedList(...)` method:

    let monitor = CoreStore.monitorSectionedList(
        From<Person>(),
        SectionBy("age") { "Age \($0)" },
        Where("title", isEqualTo: "Engineer"),
        OrderBy(.ascending("lastName"))
    )
    monitor.addObserver(self)

Objects from `ListMonitor`s created this way can be accessed either by an `IndexPath` or a tuple:

    let indexPath = IndexPath(forItem: 3, inSection: 2)
    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 (Accessors)

- `ObjectType`

  The type for the objects contained bye the `ListMonitor`

  #### Declaration

  Swift

      public typealias ObjectType = D

- `subscript(_:)`

  Returns the object at the given index within the first section. This subscript indexer is typically used for `ListMonitor`s created with `monitorList(_:)`.

  #### Declaration

  Swift

      public subscript(index: Int) -> ObjectType { get }

  #### Parameters

  `index` | the index of the object. Using an index above the valid range will raise an exception.

  #### Return Value

  the `DynamicObject` at the specified index

- `subscript(safeIndex:)`

  Returns the object at the given index, or `nil` if out of bounds. This subscript indexer is typically used for `ListMonitor`s created with `monitorList(_:)`.

  #### Declaration

  Swift

      public subscript(safeIndex index: Int) -> ObjectType? { get }

  #### Parameters

  `index` | the index for the object. Using an index above the valid range will return `nil`.

  #### Return Value

  the `DynamicObject` at the specified index, or `nil` if out of bounds

- `subscript(_:_:)`

  Returns the object at the given `sectionIndex` and `itemIndex`. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`.

  #### Declaration

  Swift

      public subscript(sectionIndex: Int, itemIndex: Int) -> ObjectType { get }

  #### Parameters

  `sectionIndex` | the section index for the object. Using a `sectionIndex` with an invalid range will raise an exception.
  `itemIndex` | the index for the object within the section. Using an `itemIndex` with an invalid range will raise an exception.

  #### Return Value

  the `DynamicObject` at the specified section and item index

- `subscript(safeSectionIndex:safeItemIndex:)`

  Returns the object at the given section and item index, or `nil` if out of bounds. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`.

  #### Declaration

  Swift

      public subscript(safeSectionIndex sectionIndex: Int, safeItemIndex itemIndex: Int) -> ObjectType? { get }

  #### Parameters

  `sectionIndex` | the section index for the object. Using a `sectionIndex` with an invalid range will return `nil`.
  `itemIndex` | the index for the object within the section. Using an `itemIndex` with an invalid range will return `nil`.

  #### Return Value

  the `DynamicObject` at the specified section and item index, or `nil` if out of bounds

- `subscript(_:)`

  Returns the object at the given `IndexPath`. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`.

  #### Declaration

  Swift

      public subscript(indexPath: IndexPath) -> ObjectType { get }

  #### Parameters

  `indexPath` | the `IndexPath` for the object. Using an `indexPath` with an invalid range will raise an exception.

  #### Return Value

  the `DynamicObject` at the specified index path

- `subscript(safeIndexPath:)`

  Returns the object at the given `IndexPath`, or `nil` if out of bounds. This subscript indexer is typically used for `ListMonitor`s created with `monitorSectionedList(_:)`.

  #### Declaration

  Swift

      public subscript(safeIndexPath indexPath: IndexPath) -> ObjectType? { get }

  #### Parameters

  `indexPath` | the `IndexPath` for the object. Using an `indexPath` with an invalid range will return `nil`.

  #### Return Value

  the `DynamicObject` at the specified index path, or `nil` if out of bounds

- `hasSections()`

  Checks if the `ListMonitor` has at least one section

  #### Declaration

  Swift

      public func hasSections() -> Bool

  #### Return Value

  `true` if at least one section exists, `false` otherwise

- `hasObjects()`

  Checks if the `ListMonitor` has at least one object in any section.

  #### Declaration

  Swift

      public func hasObjects() -> Bool

  #### Return Value

  `true` if at least one object in any section exists, `false` otherwise

- `hasObjects(in:)`

  Checks if the `ListMonitor` has at least one object the specified section.

  #### Declaration

  Swift

      public func hasObjects(in section: Int) -> Bool

  #### Parameters

  `section` | the section index. Using an index outside the valid range will return `false`.

  #### Return Value

  `true` if at least one object in the specified section exists, `false` otherwise

- `numberOfSections()`

  Returns the number of sections

  #### Declaration

  Swift

      public func numberOfSections() -> Int

  #### Return Value

  the number of sections

- `numberOfObjects()`

  Returns the number of objects in all sections

  #### Declaration

  Swift

      public func numberOfObjects() -> Int

  #### Return Value

  the number of objects in all sections

- `numberOfObjects(in:)`

  Returns the number of objects in the specified section

  #### Declaration

  Swift

      public func numberOfObjects(in section: Int) -> Int

  #### Parameters

  `section` | the section index. Using an index outside the valid range will raise an exception.

  #### Return Value

  the number of objects in the specified section

- `numberOfObjects(safelyIn:)`

  Returns the number of objects in the specified section, or `nil` if out of bounds.

  #### Declaration

  Swift

      public func numberOfObjects(safelyIn section: Int) -> Int?

  #### Parameters

  `section` | the section index. Using an index outside the valid range will return `nil`.

  #### Return Value

  the number of objects in the specified section

- `sectionInfo(at:)`

  Returns the `NSFetchedResultsSectionInfo` for the specified section

  #### Declaration

  Swift

      public func sectionInfo(at section: Int) -> NSFetchedResultsSectionInfo

  #### Parameters

  `section` | the section index. Using an index outside the valid range will raise an exception.

  #### Return Value

  the `NSFetchedResultsSectionInfo` for the specified section

- `sectionInfo(safelyAt:)`

  Returns the `NSFetchedResultsSectionInfo` for the specified section, or `nil` if out of bounds.

  #### Declaration

  Swift

      public func sectionInfo(safelyAt section: Int) -> NSFetchedResultsSectionInfo?

  #### Parameters

  `section` | the section index. Using an index outside the valid range will return `nil`.

  #### Return Value

  the `NSFetchedResultsSectionInfo` for the specified section, or `nil` if the section index is out of bounds.

- `sections()`

  Returns the `NSFetchedResultsSectionInfo`s for all sections

  #### Declaration

  Swift

      public func sections() -> [NSFetchedResultsSectionInfo]

  #### Return Value

  the `NSFetchedResultsSectionInfo`s for all sections

- `targetSection(forSectionIndexTitle:at:)`

  Returns the target section for a specified Section Index title and index.

  #### Declaration

  Swift

      public func targetSection(forSectionIndexTitle sectionIndexTitle: String, at sectionIndex: Int) -> Int

  #### Parameters

  `sectionIndexTitle` | the title of the Section Index
  `sectionIndex` | the index of the Section Index

  #### Return Value

  the target section for the specified Section Index title and index.

- `sectionIndexTitles()`

  Returns the section index titles for all sections

  #### Declaration

  Swift

      public func sectionIndexTitles() -> [String]

  #### Return Value

  the section index titles for all sections

- `index(of:)`

  Returns the index of the `DynamicObject` if it exists in the `ListMonitor`‘s fetched objects, or `nil` if not found.

  #### Declaration

  Swift

      public func index(of object: ObjectType) -> Int?

  #### Parameters

  `object` | the `DynamicObject` to search the index of

  #### Return Value

  the index of the `DynamicObject` if it exists in the `ListMonitor`‘s fetched objects, or `nil` if not found.

- `indexPath(of:)`

  Returns the `IndexPath` of the `DynamicObject` if it exists in the `ListMonitor`‘s fetched objects, or `nil` if not found.

  #### Declaration

  Swift

      public func indexPath(of object: ObjectType) -> IndexPath?

  #### Parameters

  `object` | the `DynamicObject` to search the index of

  #### Return Value

  the `IndexPath` of the `DynamicObject` if it exists in the `ListMonitor`‘s fetched objects, or `nil` if not found.

### Public (Observers)

- `addObserver(_:)`

  Registers a `ListObserver` to be notified when changes to the receiver’s list occur.

  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 `ListMonitor` unregisters previous notifications to the observer before re-registering them.

  #### Declaration

  Swift

      public func addObserver<U>(_ observer: U) where D == U.ListEntityType, U : ListObserver

  #### Parameters

  `observer` | a `ListObserver` to send change notifications to

- `addObserver(_:)`

  Registers a `ListObjectObserver` to be notified when changes to the receiver’s list occur.

  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 `ListMonitor` unregisters previous notifications to the observer before re-registering them.

  #### Declaration

  Swift

      public func addObserver<U>(_ observer: U) where D == U.ListEntityType, U : ListObjectObserver

  #### Parameters

  `observer` | a `ListObjectObserver` to send change notifications to

- `addObserver(_:)`

  Registers a `ListSectionObserver` to be notified when changes to the receiver’s list occur.

  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 `ListMonitor` unregisters previous notifications to the observer before re-registering them.

  #### Declaration

  Swift

      public func addObserver<U>(_ observer: U) where D == U.ListEntityType, U : ListSectionObserver

  #### Parameters

  `observer` | a `ListSectionObserver` to send change notifications to

- `removeObserver(_:)`

  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.

  #### Declaration

  Swift

      public func removeObserver<U>(_ observer: U) where D == U.ListEntityType, U : ListObserver

  #### Parameters

  `observer` | a `ListObserver` to unregister notifications to

### Public (Refetching)

- `isPendingRefetch`

  Returns `true` if a call to `refetch(...)` was made to the `ListMonitor` and is currently waiting for the fetching to complete. Returns `false` otherwise.

  #### Declaration

  Swift

      public private(set) var isPendingRefetch: Bool {
        get
        }

- `refetch(_:)`

  Asks the `ListMonitor` to refetch its objects using the specified series of `FetchClause`s. Note that this method does not execute the fetch immediately; the actual fetching will happen after the `NSFetchedResultsController`‘s last `controllerDidChangeContent(_:)` notification completes.

  `refetch(...)` broadcasts `listMonitorWillRefetch(...)` to its observers immediately, and then `listMonitorDidRefetch(...)` after the new fetch request completes.

  Important

  Starting CoreStore 4.0, all `FetchClause`s required by the `ListMonitor` should be provided in the arguments list of `refetch(...)`.

  #### Declaration

  Swift

      public func refetch(_ fetchClauses: FetchClause...)

  #### Parameters

  `fetchClauses` | a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.

- `refetch(_:)`

  Asks the `ListMonitor` to refetch its objects using the specified series of `FetchClause`s. Note that this method does not execute the fetch immediately; the actual fetching will happen after the `NSFetchedResultsController`‘s last `controllerDidChangeContent(_:)` notification completes.

  `refetch(...)` broadcasts `listMonitorWillRefetch(...)` to its observers immediately, and then `listMonitorDidRefetch(...)` after the new fetch request completes.

  Important

  Starting CoreStore 4.0, all `FetchClause`s required by the `ListMonitor` should be provided in the arguments list of `refetch(...)`.

  #### Declaration

  Swift

      public func refetch(_ fetchClauses: [FetchClause])

  #### Parameters

  `fetchClauses` | a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.

### Public (3rd Party Utilities)

- `userInfo`

  Allow external libraries to store custom data in the `ListMonitor`. App code should rarely have a need for this.

      enum Static {
          static var myDataKey: Void?
      }
      monitor.userInfo[&Static.myDataKey] = myObject

  Important

  Do not use this method to store thread-sensitive data.

  #### Declaration

  Swift

      public let userInfo: UserInfo

### Equatable

- `==(_:_:)`

  #### Declaration

  Swift

      public static func == (lhs: ListMonitor<ObjectType>, rhs: ListMonitor<ObjectType>) -> Bool

### Hashable

- `hash(into:)`

  #### Declaration

  Swift

      public func hash(into hasher: inout Hasher)

### CustomDebugStringConvertible

- `debugDescription`

  #### Declaration

  Swift

      public var debugDescription: String { get }

### ListMonitor where ListMonitor.ObjectType: NSManagedObject

- `objectsInAllSections()`

  Returns all objects in all sections

  #### Declaration

  Swift

      public func objectsInAllSections() -> [ObjectType]

  #### Return Value

  all objects in all sections

- `objects(in:)`

  Returns all objects in the specified section

  #### Declaration

  Swift

      public func objects(in section: Int) -> [ObjectType]

  #### Parameters

  `section` | the section index. Using an index outside the valid range will raise an exception.

  #### Return Value

  all objects in the specified section

- `objects(safelyIn:)`

  Returns all objects in the specified section, or `nil` if out of bounds.

  #### Declaration

  Swift

      public func objects(safelyIn section: Int) -> [ObjectType]?

  #### Parameters

  `section` | the section index. Using an index outside the valid range will return `nil`.

  #### Return Value

  all objects in the specified section

### ListMonitor where ListMonitor.ObjectType: CoreStoreObject

- `objectsInAllSections()`

  Returns all objects in all sections

  #### Declaration

  Swift

      public func objectsInAllSections() -> [ObjectType]

  #### Return Value

  all objects in all sections

- `objects(in:)`

  Returns all objects in the specified section

  #### Declaration

  Swift

      public func objects(in section: Int) -> [ObjectType]

  #### Parameters

  `section` | the section index. Using an index outside the valid range will raise an exception.

  #### Return Value

  all objects in the specified section

- `objects(safelyIn:)`

  Returns all objects in the specified section, or `nil` if out of bounds.

  #### Declaration

  Swift

      public func objects(safelyIn section: Int) -> [ObjectType]?

  #### Parameters

  `section` | the section index. Using an index outside the valid range will return `nil`.

  #### Return Value

  all objects in the specified section