 import UIKit
 import ReactiveCocoa
 
-public struct TableViewAdapterConfiguration<V: ViewModel> {
-	private var factories: [Int: (UITableView, V, NSIndexPath) -> UITableViewCell]
+public enum TableViewAdapterRegistration {
+	case allSections
+	case section(at: Int)
+}
+
+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)?
 
-	public init() {
-		self.factories = [:]
+	public init(set: ViewModelSet<V>) {
+		self.set = set
+		self.cellConfigurators = []
 	}
 
-	public mutating func registerForAllSection(factory: (UITableView, V, NSIndexPath) -> UITableViewCell) {
-		isUniform = true
-		factories[-1] = factory
+	private func ensureArraySize(for index: Int) {
+		if cellConfigurators.endIndex <= index {
+			cellConfigurators.appendContentsOf(Array(count: index - cellConfigurators.startIndex, repeatedValue: nil))
+		}
 	}
 
-	public mutating func registerSection(index: Int, factory: (UITableView, V, NSIndexPath) -> UITableViewCell) {
-		precondition(index >= 0, "section index must be greater than or equal to zero.")
-		factories[index] = factory
+	public func register(for type: TableViewAdapterRegistration,
+	                     with reuseIdentifier: String,
+											 applying cellConfigurator: (cell: UITableViewCell, viewModel: V) -> Void) -> TableViewAdapter {
+		switch type {
+		case let .section(index):
+			assert(index >= 0, "section index must be greater than or equal to zero.")
+			ensureArraySize(for: index)
+			cellConfigurators[index] = (reuseIdentifier, cellConfigurator)
+
+		case .allSections:
+			isUniform = true
+			cellConfigurators = [(reuseIdentifier, cellConfigurator)]
+		}
+
+		return self
 	}
 
-	public func apply(indexPath: NSIndexPath, tableView: UITableView, viewModel: V) -> UITableViewCell {
-		if isUniform {
-			return factories[-1]!(tableView, viewModel, indexPath)
-		}
-		return factories[indexPath.section]!(tableView, viewModel, indexPath)
-	}
-}
+	public func bind(tableView: UITableView) -> Disposable {
+		tableView.dataSource = self
 
-final public class TableViewAdapter<V: ViewModel>: NSObject, UITableViewDataSource {
-	private let set: ViewModelSet<V>
-	private let configuration: TableViewAdapterConfiguration<V>
-	private var isEmpty: Bool = true
-
-	public init(set: ViewModelSet<V>, configuration: TableViewAdapterConfiguration<V>) {
-		self.set = set
-		self.configuration = configuration
-	}
-
-	public func bind(tableView: UITableView) {
-		tableView.dataSource = self
-		set.eventProducer
+		defer { try! set.fetch() }
+		return set.eventProducer
 			.takeUntil(tableView.willDeinitProducer)
-			.takeUntil(willDeinitProducer)
-			.startWithNext { [unowned self, unowned tableView] in
+			.startWithNext { [unowned tableView] in
 				switch($0) {
 				case .reloaded:
 					tableView.reloadData()


				if !self.isEmpty && self.set.numberOfObjects == 0 {
					self.isEmpty = true
					self.configuration.emptySetHandler?(true)
				} else if self.isEmpty {
					self.isEmpty = false
					self.configuration.emptySetHandler?(false)
				}
		}
		try! set.fetch()
	}

	public func numberOfSectionsInTableView(tableView: UITableView) -> Int {


	public func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
		let sectionName = set.sectionName(for: section)
		return sectionNameTransform?(section, 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])

		return cell
	}

	public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
