9
9
import UIKit
10
10
import RxDataSources
11
11
import RxSwift
12
- import RxSwift
12
+ import RxCocoa
13
+
14
+ func + < T> ( lhs: [ T ] , rhs: T ) -> [ T ] {
15
+ var copy = lhs
16
+ copy. append ( rhs)
17
+ return copy
18
+ }
19
+
20
+ enum TableViewEditingCommand < T> {
21
+ case AppendItem( item: T , section: Int )
22
+ case MoveItem( sourceIndex: NSIndexPath , destinationIndex: NSIndexPath )
23
+ case DeleteItem( NSIndexPath )
24
+ }
13
25
14
- extension Array {
15
- subscript ( safe index: Int ) -> Element ? {
16
- return indices ~= index
17
- ? self [ index]
18
- : nil
26
+ struct SectionedTableViewState < T: AnimatableSectionModelType > {
27
+ private var sections : [ T ]
28
+
29
+ init ( sections: [ T ] ) {
30
+ self . sections = sections
31
+ }
32
+
33
+ func executeCommand( command: TableViewEditingCommand < T . Item > ) -> SectionedTableViewState {
34
+ switch command {
35
+ case . AppendItem( let appendEvent) :
36
+ var sections = self . sections
37
+ let items = sections [ appendEvent. section] . items + appendEvent. item
38
+ sections [ appendEvent. section] = T ( original: sections [ appendEvent. section] , items: items)
39
+ return SectionedTableViewState ( sections: sections)
40
+ case . DeleteItem( let indexPath) :
41
+ var sections = self . sections
42
+ var items = sections [ indexPath. section] . items
43
+ items. removeAtIndex ( indexPath. row)
44
+ sections [ indexPath. section] = T ( original: sections [ indexPath. section] , items: items)
45
+ return SectionedTableViewState ( sections: sections)
46
+ case . MoveItem( let moveEvent) :
47
+ var sections = self . sections
48
+ var sourceItems = sections [ moveEvent. sourceIndex. section] . items
49
+ var destinationItems = sections [ moveEvent. destinationIndex. section] . items
50
+
51
+ if moveEvent. sourceIndex. section == moveEvent. destinationIndex. section {
52
+ destinationItems. insert ( destinationItems. removeAtIndex ( moveEvent. sourceIndex. row) ,
53
+ atIndex: moveEvent. destinationIndex. row)
54
+ let destinationSection = T ( original: sections [ moveEvent. destinationIndex. section] , items: destinationItems)
55
+ sections [ moveEvent. sourceIndex. section] = destinationSection
56
+
57
+ return SectionedTableViewState ( sections: sections)
58
+ } else {
59
+ let item = sourceItems. removeAtIndex ( moveEvent. sourceIndex. row)
60
+ destinationItems. insert ( item, atIndex: moveEvent. destinationIndex. row)
61
+ let sourceSection = T ( original: sections [ moveEvent. sourceIndex. section] , items: sourceItems)
62
+ let destinationSection = T ( original: sections [ moveEvent. destinationIndex. section] , items: destinationItems)
63
+ sections [ moveEvent. sourceIndex. section] = sourceSection
64
+ sections [ moveEvent. destinationIndex. section] = destinationSection
65
+
66
+ return SectionedTableViewState ( sections: sections)
67
+ }
68
+ }
69
+ }
70
+ }
71
+
72
+ class TableViewEditingCommandsViewModel < T: AnimatableSectionModelType > {
73
+
74
+ let sectionsChange : Observable < [ T ] >
75
+
76
+ init ( uiTriggers: ( itemAdded: Observable < ( item: T . Item , section: Int ) > ,
77
+ itemDeleted: Observable < NSIndexPath > ,
78
+ itemMoved: Observable < ItemMovedEvent > ) ,
79
+ initialData: SectionedTableViewState < T > ) {
80
+
81
+ let addComand = uiTriggers. itemAdded
82
+ . map {
83
+ return TableViewEditingCommand< T . Item> . AppendItem( item: $0. item, section: $0. section)
84
+ }
85
+ let deleteCommand = uiTriggers. itemDeleted
86
+ . map {
87
+ return TableViewEditingCommand< T . Item> . DeleteItem( $0)
88
+ }
89
+ let movedCommand = uiTriggers. itemMoved
90
+ . map { ( sourceIndex, destinationIndex) -> TableViewEditingCommand < T . Item > in
91
+ return TableViewEditingCommand< T . Item> . MoveItem( sourceIndex: sourceIndex, destinationIndex: destinationIndex)
92
+ }
93
+
94
+ sectionsChange = Observable . of ( addComand, deleteCommand, movedCommand)
95
+ . merge ( )
96
+ . scan ( initialData) {
97
+ return $0. executeCommand ( $1)
98
+ }
99
+ . map {
100
+ $0. sections
101
+ }
102
+ . shareReplay ( 1 )
19
103
}
20
104
}
21
105
@@ -30,37 +114,24 @@ class EditingExampleViewController: UIViewController {
30
114
super. viewDidLoad ( )
31
115
32
116
let dataSource = RxTableViewSectionedAnimatedDataSource < NumberSection > ( )
33
-
34
- let addition = addButton. rx_tap. asObservable ( )
35
- . scan ( 0 ) { ( acum, _) -> Int in
36
- return acum + 1
37
- }
38
- . map { [ unowned dataSource] i -> [ NumberSection ] in
39
- var section = dataSource. sectionModels [ safe: 0 ]
40
- section? . appendItem ( IntItem ( number: i, date: NSDate ( ) ) )
41
-
42
- return [ section ?? NumberSection ( header: " " ,
43
- numbers: [ IntItem ( number: i, date: NSDate ( ) ) ] ,
44
- updated: NSDate ( ) ) ]
117
+ let sections : [ NumberSection ] = [ NumberSection ( header: " Section 1 " , numbers: [ ] , updated: NSDate ( ) ) ,
118
+ NumberSection ( header: " Section 2 " , numbers: [ ] , updated: NSDate ( ) ) ,
119
+ NumberSection ( header: " Section 3 " , numbers: [ ] , updated: NSDate ( ) ) ]
120
+ let initialState = SectionedTableViewState < NumberSection > ( sections: sections)
121
+ let itemAdded = addButton. rx_tap
122
+ . scan ( 0 , accumulator: { $0. 0 + 1 } )
123
+ . map { number -> ( item: IntItem , section: Int ) in
124
+ let randSection = Int ( arc4random_uniform ( UInt32 ( sections. count) ) )
125
+ return ( IntItem ( number: number, date: NSDate ( ) ) , randSection)
45
126
}
127
+ let itemDeleted = tableView. rx_itemDeleted. asObservable ( )
128
+ let itemMoved = tableView. rx_itemMoved. asObservable ( )
46
129
47
- let deletion = tableView. rx_itemDeleted. asObservable ( )
48
- . map { [ unowned dataSource] indexPath -> [ NumberSection ] in
49
- var section = dataSource. sectionModels [ 0 ]
50
- section. removeItemAtIndex ( indexPath. row)
51
- return [ section]
52
- }
130
+ let viewModel = TableViewEditingCommandsViewModel < NumberSection > ( uiTriggers: ( itemAdded: itemAdded,
131
+ itemDeleted: itemDeleted,
132
+ itemMoved: itemMoved) , initialData: initialState)
53
133
54
- let move = tableView. rx_itemMoved. asObservable ( )
55
- . map { moveEvent -> [ NumberSection ] in
56
- var section = dataSource. sectionModels [ 0 ]
57
- section. moveItemAtIndex ( moveEvent. sourceIndex. row,
58
- toIndex: moveEvent. destinationIndex. row)
59
- return [ section]
60
- }
61
-
62
- Observable . of ( addition, deletion, move)
63
- . merge ( )
134
+ viewModel. sectionsChange
64
135
. bindTo ( tableView. rx_itemsAnimatedWithDataSource ( dataSource) )
65
136
. addDisposableTo ( disposeBag)
66
137
0 commit comments