Skip to content

Commit a8e2785

Browse files
committed
Improves lifetime.
1 parent b99b944 commit a8e2785

7 files changed

+116
-15
lines changed

Example/Example3_TableViewEditing.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class EditingExampleViewController: UIViewController {
3939
let movedCommand = tableView.rx_itemMoved
4040
.map(TableViewEditingCommand.MoveItem)
4141

42+
skinTableViewDataSource(dataSource)
4243
Observable.of(addCommand, deleteCommand, movedCommand)
4344
.merge()
4445
.scan(initialState) {
@@ -51,8 +52,6 @@ class EditingExampleViewController: UIViewController {
5152
.shareReplay(1)
5253
.bindTo(tableView.rx_itemsWithDataSource(dataSource))
5354
.addDisposableTo(disposeBag)
54-
55-
skinTableViewDataSource(dataSource)
5655
}
5756

5857
override func viewDidAppear(animated: Bool) {

Sources/DataSources+Rx/RxCollectionViewSectionedAnimatedDataSource.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ public class RxCollectionViewSectionedAnimatedDataSource<S: AnimatableSectionMod
2929

3030
public func collectionView(collectionView: UICollectionView, observedEvent: Event<Element>) {
3131
UIBindingObserver(UIElement: self) { dataSource, newSections in
32+
#if DEBUG
33+
self._dataSourceBound = true
34+
#endif
3235
if !self.dataSet {
3336
self.dataSet = true
3437
dataSource.setSections(newSections)

Sources/DataSources+Rx/RxCollectionViewSectionedReloadDataSource.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ public class RxCollectionViewSectionedReloadDataSource<S: SectionModelType>
2525

2626
public func collectionView(collectionView: UICollectionView, observedEvent: Event<Element>) {
2727
UIBindingObserver(UIElement: self) { dataSource, element in
28+
#if DEBUG
29+
self._dataSourceBound = true
30+
#endif
2831
dataSource.setSections(element)
2932
collectionView.reloadData()
3033
}.on(observedEvent)

Sources/DataSources+Rx/RxTableViewSectionedAnimatedDataSource.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ public class RxTableViewSectionedAnimatedDataSource<S: AnimatableSectionModelTyp
2828

2929
public func tableView(tableView: UITableView, observedEvent: Event<Element>) {
3030
UIBindingObserver(UIElement: self) { dataSource, newSections in
31+
#if DEBUG
32+
self._dataSourceBound = true
33+
#endif
3134
if !self.dataSet {
3235
self.dataSet = true
3336
dataSource.setSections(newSections)

Sources/DataSources+Rx/RxTableViewSectionedReloadDataSource.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public class RxTableViewSectionedReloadDataSource<S: SectionModelType>
2424

2525
public func tableView(tableView: UITableView, observedEvent: Event<Element>) {
2626
UIBindingObserver(UIElement: self) { dataSource, element in
27+
#if DEBUG
28+
self._dataSourceBound = true
29+
#endif
2730
dataSource.setSections(element)
2831
tableView.reloadData()
2932
}.on(observedEvent)

Sources/DataSources/CollectionViewSectionedDataSource.swift

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,19 @@ public class CollectionViewSectionedDataSource<S: SectionModelType>
7272
public typealias Section = S
7373
public typealias CellFactory = (CollectionViewSectionedDataSource<S>, UICollectionView, NSIndexPath, I) -> UICollectionViewCell
7474
public typealias SupplementaryViewFactory = (CollectionViewSectionedDataSource<S>, UICollectionView, String, NSIndexPath) -> UICollectionReusableView
75+
76+
#if DEBUG
77+
// If data source has already been bound, then mutating it
78+
// afterwards isn't something desired.
79+
// This simulates immutability after binding
80+
var _dataSourceBound: Bool = false
81+
82+
private func ensureNotMutatedAfterBinding() {
83+
assert(!_dataSourceBound, "Data source is already bound. Please write this line before binding call (`bindTo`, `drive`). Data source must first be completely configured, and then bound after that, otherwise there could be runtime bugs, glitches, or partial malfunctions.")
84+
}
7585

86+
#endif
87+
7688
// This structure exists because model can be mutable
7789
// In that case current state value should be preserved.
7890
// The state that needs to be preserved is ordering of items in section
@@ -104,7 +116,13 @@ public class CollectionViewSectionedDataSource<S: SectionModelType>
104116
self._sectionModels = sections.map { SectionModelSnapshot(model: $0, items: $0.items) }
105117
}
106118

107-
public var configureCell: CellFactory! = nil
119+
public var configureCell: CellFactory! = nil {
120+
didSet {
121+
#if DEBUG
122+
ensureNotMutatedAfterBinding()
123+
#endif
124+
}
125+
}
108126

109127
@available(*, deprecated=0.8.1, renamed="configureCell")
110128
public var cellFactory: CellFactory! {
@@ -116,10 +134,28 @@ public class CollectionViewSectionedDataSource<S: SectionModelType>
116134
}
117135
}
118136

119-
public var supplementaryViewFactory: SupplementaryViewFactory
137+
public var supplementaryViewFactory: SupplementaryViewFactory {
138+
didSet {
139+
#if DEBUG
140+
ensureNotMutatedAfterBinding()
141+
#endif
142+
}
143+
}
120144

121-
public var moveItem: ((CollectionViewSectionedDataSource<S>, sourceIndexPath:NSIndexPath, destinationIndexPath:NSIndexPath) -> Void)?
122-
public var canMoveItemAtIndexPath: ((CollectionViewSectionedDataSource<S>, indexPath:NSIndexPath) -> Bool)?
145+
public var moveItem: ((CollectionViewSectionedDataSource<S>, sourceIndexPath:NSIndexPath, destinationIndexPath:NSIndexPath) -> Void)? {
146+
didSet {
147+
#if DEBUG
148+
ensureNotMutatedAfterBinding()
149+
#endif
150+
}
151+
}
152+
public var canMoveItemAtIndexPath: ((CollectionViewSectionedDataSource<S>, indexPath:NSIndexPath) -> Bool)? {
153+
didSet {
154+
#if DEBUG
155+
ensureNotMutatedAfterBinding()
156+
#endif
157+
}
158+
}
123159

124160
public override init() {
125161
self.configureCell = {_, _, _, _ in return (nil as UICollectionViewCell?)! }

Sources/DataSources/TableViewSectionedDataSource.swift

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,19 @@ public class RxTableViewSectionedDataSource<S: SectionModelType>
116116
public typealias I = S.Item
117117
public typealias Section = S
118118
public typealias CellFactory = (RxTableViewSectionedDataSource<S>, UITableView, NSIndexPath, I) -> UITableViewCell
119+
120+
#if DEBUG
121+
// If data source has already been bound, then mutating it
122+
// afterwards isn't something desired.
123+
// This simulates immutability after binding
124+
var _dataSourceBound: Bool = false
125+
126+
private func ensureNotMutatedAfterBinding() {
127+
assert(!_dataSourceBound, "Data source is already bound. Please write this line before binding call (`bindTo`, `drive`). Data source must first be completely configured, and then bound after that, otherwise there could be runtime bugs, glitches, or partial malfunctions.")
128+
}
119129

130+
#endif
131+
120132
// This structure exists because model can be mutable
121133
// In that case current state value should be preserved.
122134
// The state that needs to be preserved is ordering of items in section
@@ -154,22 +166,64 @@ public class RxTableViewSectionedDataSource<S: SectionModelType>
154166
self._sectionModels = sections.map { SectionModelSnapshot(model: $0, items: $0.items) }
155167
}
156168

157-
public var configureCell: CellFactory! = nil
169+
public var configureCell: CellFactory! = nil {
170+
didSet {
171+
#if DEBUG
172+
ensureNotMutatedAfterBinding()
173+
#endif
174+
}
175+
}
158176

159-
public var titleForHeaderInSection: ((RxTableViewSectionedDataSource<S>, section: Int) -> String?)?
160-
public var titleForFooterInSection: ((RxTableViewSectionedDataSource<S>, section: Int) -> String?)?
177+
public var titleForHeaderInSection: ((RxTableViewSectionedDataSource<S>, section: Int) -> String?)? {
178+
didSet {
179+
#if DEBUG
180+
ensureNotMutatedAfterBinding()
181+
#endif
182+
}
183+
}
184+
public var titleForFooterInSection: ((RxTableViewSectionedDataSource<S>, section: Int) -> String?)? {
185+
didSet {
186+
#if DEBUG
187+
ensureNotMutatedAfterBinding()
188+
#endif
189+
}
190+
}
161191

162-
public var canEditRowAtIndexPath: ((RxTableViewSectionedDataSource<S>, indexPath: NSIndexPath) -> Bool)?
192+
public var canEditRowAtIndexPath: ((RxTableViewSectionedDataSource<S>, indexPath: NSIndexPath) -> Bool)? {
193+
didSet {
194+
#if DEBUG
195+
ensureNotMutatedAfterBinding()
196+
#endif
197+
}
198+
}
199+
163200
override public var canEditRowAtIndexPathImplemented: Bool {
164201
let result = canEditRowAtIndexPath != nil
165202
return result
166203
}
167-
public var canMoveRowAtIndexPath: ((RxTableViewSectionedDataSource<S>, indexPath: NSIndexPath) -> Bool)?
168-
169-
public var sectionIndexTitles: ((RxTableViewSectionedDataSource<S>) -> [String]?)?
170-
public var sectionForSectionIndexTitle:((RxTableViewSectionedDataSource<S>, title: String, index: Int) -> Int)?
204+
public var canMoveRowAtIndexPath: ((RxTableViewSectionedDataSource<S>, indexPath: NSIndexPath) -> Bool)? {
205+
didSet {
206+
#if DEBUG
207+
ensureNotMutatedAfterBinding()
208+
#endif
209+
}
210+
}
211+
171212

172-
public var rowAnimation: UITableViewRowAnimation = .Automatic
213+
public var sectionIndexTitles: ((RxTableViewSectionedDataSource<S>) -> [String]?)? {
214+
didSet {
215+
#if DEBUG
216+
ensureNotMutatedAfterBinding()
217+
#endif
218+
}
219+
}
220+
public var sectionForSectionIndexTitle:((RxTableViewSectionedDataSource<S>, title: String, index: Int) -> Int)? {
221+
didSet {
222+
#if DEBUG
223+
ensureNotMutatedAfterBinding()
224+
#endif
225+
}
226+
}
173227

174228
public override init() {
175229
super.init()

0 commit comments

Comments
 (0)