 /// You must use this controller only on the same thread as the associated context.
 ///
 final public class ObjectSet<E: Object>: Base {
-  public let fetchRequest: NSFetchRequest
-  public let entity: NSEntityDescription
-
-  public let sectionNameKeyPath: String?
-  public let _sectionNameKeyPath: [String]?
-  public let defaultSectionName: String
-
-  public let sectionNameOrdering: NSComparisonResult
-  public let objectSortDescriptors: [NSSortDescriptor]
+	public let fetchRequest: NSFetchRequest
+	public let entity: NSEntityDescription
+
+	public let sectionNameKeyPath: String?
+	public let _sectionNameKeyPath: [String]?
+	public let defaultSectionName: String
+
+	public let sectionNameOrdering: NSComparisonResult
+	public let objectSortDescriptors: [NSSortDescriptor]
 
 	// An ObjectSet retains the managed object context.
 	private(set) public weak var context: ObjectContext!

		let indiceOfDeletedSections = NSMutableIndexSet()
		let indiceOfInsertedSections = NSMutableIndexSet()

    indexPathsOfInsertedRows.reserveCapacity(externalChanges.insertedObjectsCount)
    indexPathsOfDeletedRows.reserveCapacity(externalChanges.deletedObjectsCount)
    indexPathsOfUpdatedRows.reserveCapacity(externalChanges.updatedObjectsCount)
    indexPathsOfMovedRows.reserveCapacity(originsOfMoved.capacity)

    for (sectionName, objects) in externalChanges.deletedObjects {
			guard let sectionIndex = oldSections.indexFor(sectionName) else {
				assertionFailure("Section `\(sectionName)` should be in the result set, but it cannot be found.")
				continue
			}

      for object in objects {
				guard let rowIndex = oldSections[sectionIndex].indexOf(object) else {
					assertionFailure("Object `\(object)` should be in the section `\(sectionName)`, but it cannot be found.")
					continue
				}

        let indexPath = NSIndexPath(forRow: rowIndex, inSection: sectionIndex)
        indexPathsOfDeletedRows.append(indexPath)
      }
    }

    for (oldSectionName, objects) in externalChanges.movedObjects {
			guard let oldSectionIndex = oldSections.indexFor(oldSectionName) else {
				assertionFailure("Section `\(oldSectionName)` should be in the result set, but cannot be found.")
				continue
			}

      for object in objects {
				guard let rowIndex = oldSections[oldSectionIndex].indexOf(object) else {
					assertionFailure("Object `\(object)` should be in the section `\(oldSectionName)`, but it cannot be found.")
					continue
				}

				let indexPath = NSIndexPath(forRow: rowIndex, inSection: oldSectionIndex)
        originsOfMoved.append(indexPath)
      }
    }
    
    for indexPath in originsOfMoved {
      let object = oldSections[indexPath.section][indexPath.row]
      let sectionName = sectionNameFor(object)
      inboundObjects.insert(object, inSetForKey: sectionName)
    }

    var pendingDelete = ContiguousArray<NSIndexPath>()
		pendingDelete.appendContentsOf(originsOfMoved)
		pendingDelete.appendContentsOf(indexPathsOfDeletedRows)
    pendingDelete.sortInPlace { $0.row > $1.row }

    for indexPath in pendingDelete {
      updatedSections[indexPath.section].removeAtIndex(indexPath.row)
    }

    for sectionIndex in updatedSections.indices {
      if updatedSections[sectionIndex].count == 0 {
        indiceOfDeletedSections.addIndex(sectionIndex)
      }
    }

    for sectionIndex in indiceOfDeletedSections.reverse() {
      updatedSections.removeAtIndex(sectionIndex)
    }

    for (sectionName, objects) in externalChanges.insertedObjects {
      if let sectionIndex = updatedSections.indexFor(sectionName) {
        updatedSections[sectionIndex].appendContentsOf(objects)
      } else {
				let index = updatedSections.insertSection(sectionName,
					ordering: sectionNameOrdering,
					section: ObjectSetSection(name: sectionName,
						array: Array(objects)))

        indiceOfInsertedSections.addIndex(index)
      }
    }

    for (sectionName, objects) in inboundObjects {
      if let sectionIndex = updatedSections.indexFor(sectionName) {
        updatedSections[sectionIndex].appendContentsOf(objects)
      } else {
        let index = updatedSections.insertSection(sectionName,
					ordering: sectionNameOrdering,
					section: ObjectSetSection(name: sectionName,
						array: Array(objects)))

        indiceOfInsertedSections.addIndex(index)
      }
    }

    for sectionIndex in updatedSections.indices {
			let sectionName = updatedSections[sectionIndex].name
			let oldSectionIndex = oldSections.indexFor(sectionName)

      updatedSections[sectionIndex]._sortInPlace(objectSortDescriptors)

      for (objectIndex, object) in updatedSections[sectionIndex].enumerate() {
        if let oldSectionIndex = oldSectionIndex {
          if objectIndex < oldSections[oldSectionIndex].count && object == oldSections[oldSectionIndex][objectIndex] {
            if let isUpdated = externalChanges.updatedObjects[sectionName]?.contains(object) where isUpdated {
              let indexPath = NSIndexPath(forRow: objectIndex, inSection: sectionIndex)
              indexPathsOfUpdatedRows.append(indexPath)
            }
            continue
          }
        }

        if let isInserted = externalChanges.insertedObjects[sectionName]?.contains(object) where isInserted {
          indexPathsOfInsertedRows.append(NSIndexPath(forRow: objectIndex, inSection: sectionIndex))
          continue
        }

        if let inboundIndex = inboundObjects[sectionName]?.indexOf(object) {
          if indiceOfDeletedSections.contains(originsOfMoved[inboundIndex].section) {
            let indexPath = NSIndexPath(forRow: objectIndex, inSection: sectionIndex)
            indexPathsOfInsertedRows.append(indexPath)
          } else if indiceOfInsertedSections.contains(sectionIndex) {
            let indexPath = NSIndexPath(forRow: objectIndex, inSection: sectionIndex)
            indexPathsOfDeletedRows.append(originsOfMoved[inboundIndex])
            indexPathsOfInsertedRows.append(indexPath)
          } else {
            let from = originsOfMoved[inboundIndex]
            let to = NSIndexPath(forRow: objectIndex, inSection: sectionIndex)
            indexPathsOfMovedRows.append((from, to))
          }
          continue
        }

        if let oldSectionIndex = oldSectionIndex, oldIndex = oldSections[oldSectionIndex].indexOf(object) {
          let from = NSIndexPath(forRow: oldIndex, inSection: oldSectionIndex)
          let to = NSIndexPath(forRow: objectIndex, inSection: sectionIndex)
          indexPathsOfMovedRows.append((from, to))
          continue
        }
      }
    }
    
    sections = updatedSections

		let resultSetChanges = ReactiveSetChanges(indexPathsOfDeletedRows: indexPathsOfDeletedRows,
			indexPathsOfInsertedRows: indexPathsOfInsertedRows,
			indexPathsOfMovedRows: indexPathsOfMovedRows,
			indexPathsOfUpdatedRows: indexPathsOfUpdatedRows,
			indiceOfInsertedSections: indiceOfInsertedSections,
			indiceOfDeletedSections: indiceOfDeletedSections)

    eventObserver?.sendNext(.Updated(resultSetChanges))
  }
  
  deinit {
    eventObserver?.sendCompleted()
  }
}

extension ObjectSet: ReactiveSet {

			}
		}

		isFetched = true
	}

	private func sectionNameFor(object: E) -> ReactiveSetSectionName {
		if let keyPath = self.sectionNameKeyPath {
			switch object.valueForKeyPath(keyPath) {
			case let name as String:
				return ReactiveSetSectionName(name)
			case let name as NSNumber:
				return ReactiveSetSectionName(name.stringValue)
			default:
				return ReactiveSetSectionName(nil)
			}
		}
		return ReactiveSetSectionName(nil)
	}

	private func shouldInclude(object: NSManagedObject) -> E? {
		if object.entity.name == entity.name {
			if fetchRequest.predicate?.evaluateWithObject(object) ?? true {
				return object as? E
			}
		}
		return nil
	}

	/// Merge changes since last posting of NSManagedContextObjectsDidChangeNotification.
	@objc private func mergeChangesFrom(notification: NSNotification) {
		if let changes = extractExternalChangesFrom(notification) {
			apply(changes)
		}
	}

	private func extractExternalChangesFrom(notification: NSNotification) -> ExternalChanges<E>? {
		guard let userInfo = notification.userInfo else {
			return nil
		}

		var notification = ExternalChanges<E>()

		if let insertedObjects = userInfo[NSInsertedObjectsKey] as? Set<NSManagedObject> {
			for object in insertedObjects {
				if let object = shouldInclude(object) {
					let sectionName = sectionNameFor(object)
					notification.insertedObjects.insert(object, inSetForKey: sectionName)
					notification.insertedObjectsCount = notification.insertedObjectsCount + 1
				}
			}
		}

		if let deletedObjects = userInfo[NSDeletedObjectsKey] as? Set<NSManagedObject> {
			for object in deletedObjects {
				if let object = shouldInclude(object) {
					let sectionName = sectionNameFor(object)
					notification.deletedObjects.insert(object, inSetForKey: sectionName)
					notification.deletedObjectsCount = notification.deletedObjectsCount + 1
				}
			}
		}

		if let updatedObjects = userInfo[NSUpdatedObjectsKey] as? Set<NSManagedObject> {
			for object in updatedObjects {
				if let object = shouldInclude(object) {
					let sectionName: ReactiveSetSectionName

					if sectionNameKeyPath != nil {
						let __object: E = _sectionNameKeyPath!.count > 1
							? object.valueForKeyPath(_sectionNameKeyPath!.first!) as! E
							: object

						sectionName = sectionNameFor(object)

						let changedDict = __object.changedValuesForCurrentEvent()
						if changedDict.keys.contains(_sectionNameKeyPath!.last!) {
