 
 final public class TableViewAdapter<V: ViewModel>: NSObject, UITableViewDataSource {
 	private let set: ViewModelSet<V>
-	private var isEmpty: Bool = true
 
 	private var cellConfigurators: [(reuseIdentifier: String, configurator: (cell: UITableViewCell, viewModel: V) -> Void)?]
-	public var isUniform = false
-	public var shouldReloadRowsForUpdatedObjects = false
-	public var rowAnimation: UITableViewRowAnimation = .Automatic
-	public var sectionNameTransform: ((Int, String?) -> String?)?
-	public var emptySetHandler: (Bool -> Void)?
+	private var isUniform = false
+
+	private var shouldReloadRowsForUpdatedObjects = false
+
+	private var insertingAnimation: UITableViewRowAnimation = .Automatic
+	private var deletingAnimation: UITableViewRowAnimation = .Automatic
+	private var updatingAnimation: UITableViewRowAnimation = .Automatic
+
+	private var sectionNameMapper: ((position: Int, persistedName: String?) -> String?)?
+
+	private var isEmpty: Bool = true
+	public var emptiedObserver: (() -> Void)?
+	public var unemptiedObserver: (() -> Void)?
 
 	public init(set: ViewModelSet<V>) {
 		self.set = set

		return self
	}

	public func bind(tableView: UITableView) -> Disposable {
		tableView.dataSource = self



					if let indexPaths = changes.insertedRows {
						tableView.insertRowsAtIndexPaths(indexPaths.map { NSIndexPath(converting: $0) },
							withRowAnimation: self.insertingAnimation)
					}

					tableView.endUpdates()
				}

				if !self.isEmpty && self.set.map({ $0.count }).reduce(0, combine: +) == 0 {
					self.isEmpty = true
					self.emptiedObserver?()
				} else if self.isEmpty {
					self.isEmpty = false
					self.unemptiedObserver?()
				}
		}
	}

	/// MARK: `UITableViewDataSource` conformance

	public func numberOfSectionsInTableView(tableView: UITableView) -> Int {
		return set.count
	}

	public func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
		let sectionName = set[section.typeErased()].name.value
		return sectionNameMapper?(position: section, persistedName: sectionName) ?? sectionName
	}

	public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
		let (reuseIdentifier, configurator) = cellConfigurators[isUniform ? 0 : indexPath.section]!
		let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier,
		                                                       forIndexPath: indexPath)
		configurator(cell: cell, viewModel: set[indexPath.section.typeErased()][indexPath.row.typeErased()])

		return cell
	}

	public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
		return set[section.typeErased()].count
	}
}