Skip to content

Commit ac314fe

Browse files
committed
Fixes problems with moving through sections.
1 parent e4b6d09 commit ac314fe

15 files changed

+214
-228
lines changed

Example/Base.lproj/Main.storyboard

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15A284" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="dhj-Tp-dZp">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="dhj-Tp-dZp">
33
<dependencies>
44
<deployment identifier="iOS"/>
55
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
@@ -25,7 +25,7 @@
2525
<rect key="frame" x="0.0" y="0.0" width="567" height="43.5"/>
2626
<autoresizingMask key="autoresizingMask"/>
2727
<subviews>
28-
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Rundomize Example" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="lN3-iK-CfR">
28+
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Randomize Example" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="lN3-iK-CfR">
2929
<rect key="frame" x="15" y="0.0" width="550" height="43.5"/>
3030
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
3131
<fontDescription key="fontDescription" type="system" pointSize="16"/>
@@ -58,14 +58,6 @@
5858
<segue destination="f4D-bS-ukh" kind="push" id="vUe-QP-Eup"/>
5959
</connections>
6060
</tableViewCell>
61-
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="lg9-bj-acK">
62-
<rect key="frame" x="0.0" y="123" width="600" height="44"/>
63-
<autoresizingMask key="autoresizingMask"/>
64-
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="lg9-bj-acK" id="Z6T-WW-Dgn">
65-
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
66-
<autoresizingMask key="autoresizingMask"/>
67-
</tableViewCellContentView>
68-
</tableViewCell>
6961
</cells>
7062
</tableViewSection>
7163
</sections>

Example/EditingExampleViewController.swift

Lines changed: 85 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -11,98 +11,6 @@ import RxDataSources
1111
import RxSwift
1212
import RxCocoa
1313

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-
}
25-
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)
103-
}
104-
}
105-
10614
class EditingExampleViewController: UIViewController {
10715

10816
@IBOutlet weak var addButton: UIBarButtonItem!
@@ -117,21 +25,34 @@ class EditingExampleViewController: UIViewController {
11725
let sections: [NumberSection] = [NumberSection(header: "Section 1", numbers: [], updated: NSDate()),
11826
NumberSection(header: "Section 2", numbers: [], updated: NSDate()),
11927
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
28+
29+
let initialState = SectionedTableViewState(sections: sections)
30+
let addCommand = addButton.rx_tap
31+
.scan(0) { x, _ in x + 1 }
32+
.map { (number: Int) -> TableViewEditingCommand in
12433
let randSection = Int(arc4random_uniform(UInt32(sections.count)))
125-
return (IntItem(number: number, date: NSDate()), randSection)
34+
let item = IntItem(number: number, date: NSDate())
35+
return TableViewEditingCommand.AppendItem(item: item, section: randSection)
36+
}
37+
let deleteCommand = tableView.rx_itemDeleted.asObservable()
38+
.map {
39+
return TableViewEditingCommand.DeleteItem($0)
40+
}
41+
let movedCommand = tableView.rx_itemMoved
42+
.map { (sourceIndex, destinationIndex) in
43+
return TableViewEditingCommand.MoveItem(sourceIndex: sourceIndex, destinationIndex: destinationIndex)
12644
}
127-
let itemDeleted = tableView.rx_itemDeleted.asObservable()
128-
let itemMoved = tableView.rx_itemMoved.asObservable()
129-
130-
let viewModel = TableViewEditingCommandsViewModel<NumberSection>(uiTriggers: (itemAdded: itemAdded,
131-
itemDeleted: itemDeleted,
132-
itemMoved: itemMoved), initialData: initialState)
13345

134-
viewModel.sectionsChange
46+
Observable.of(addCommand, deleteCommand, movedCommand)
47+
.merge()
48+
.scan(initialState) {
49+
return $0.executeCommand($1)
50+
}
51+
.startWith(initialState)
52+
.map {
53+
$0.sections
54+
}
55+
.shareReplay(1)
13556
.bindTo(tableView.rx_itemsAnimatedWithDataSource(dataSource))
13657
.addDisposableTo(disposeBag)
13758

@@ -169,3 +90,63 @@ class EditingExampleViewController: UIViewController {
16990
}
17091
}
17192
}
93+
94+
enum TableViewEditingCommand {
95+
case AppendItem(item: IntItem, section: Int)
96+
case MoveItem(sourceIndex: NSIndexPath, destinationIndex: NSIndexPath)
97+
case DeleteItem(NSIndexPath)
98+
}
99+
100+
// This is the part
101+
102+
struct SectionedTableViewState {
103+
private var sections: [NumberSection]
104+
105+
init(sections: [NumberSection]) {
106+
self.sections = sections
107+
}
108+
109+
func executeCommand(command: TableViewEditingCommand) -> SectionedTableViewState {
110+
switch command {
111+
case .AppendItem(let appendEvent):
112+
var sections = self.sections
113+
let items = sections[appendEvent.section].items + appendEvent.item
114+
sections[appendEvent.section] = NumberSection(original: sections[appendEvent.section], items: items)
115+
return SectionedTableViewState(sections: sections)
116+
case .DeleteItem(let indexPath):
117+
var sections = self.sections
118+
var items = sections[indexPath.section].items
119+
items.removeAtIndex(indexPath.row)
120+
sections[indexPath.section] = NumberSection(original: sections[indexPath.section], items: items)
121+
return SectionedTableViewState(sections: sections)
122+
case .MoveItem(let moveEvent):
123+
var sections = self.sections
124+
var sourceItems = sections[moveEvent.sourceIndex.section].items
125+
var destinationItems = sections[moveEvent.destinationIndex.section].items
126+
127+
if moveEvent.sourceIndex.section == moveEvent.destinationIndex.section {
128+
destinationItems.insert(destinationItems.removeAtIndex(moveEvent.sourceIndex.row),
129+
atIndex: moveEvent.destinationIndex.row)
130+
let destinationSection = NumberSection(original: sections[moveEvent.destinationIndex.section], items: destinationItems)
131+
sections[moveEvent.sourceIndex.section] = destinationSection
132+
133+
return SectionedTableViewState(sections: sections)
134+
} else {
135+
let item = sourceItems.removeAtIndex(moveEvent.sourceIndex.row)
136+
destinationItems.insert(item, atIndex: moveEvent.destinationIndex.row)
137+
let sourceSection = NumberSection(original: sections[moveEvent.sourceIndex.section], items: sourceItems)
138+
let destinationSection = NumberSection(original: sections[moveEvent.destinationIndex.section], items: destinationItems)
139+
sections[moveEvent.sourceIndex.section] = sourceSection
140+
sections[moveEvent.destinationIndex.section] = destinationSection
141+
142+
return SectionedTableViewState(sections: sections)
143+
}
144+
}
145+
}
146+
}
147+
148+
func + <T>(lhs: [T], rhs: T) -> [T] {
149+
var copy = lhs
150+
copy.append(rhs)
151+
return copy
152+
}

Podfile.lock

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
PODS:
2-
- RxCocoa (2.2.0):
3-
- RxSwift (~> 2.2)
4-
- RxSwift (2.2.0)
2+
- RxCocoa (2.3.1):
3+
- RxSwift (~> 2.3.1)
4+
- RxSwift (2.3.1)
55

66
DEPENDENCIES:
7-
- RxCocoa (~> 2.0)
8-
- RxSwift (~> 2.0)
7+
- RxCocoa (~> 2.3.1)
8+
- RxSwift (~> 2.3.1)
99

1010
SPEC CHECKSUMS:
11-
RxCocoa: 42efb7a7145a8d1d5878e94ce48a580d29e0c796
12-
RxSwift: b8a749f2204c6c7a5c29b306a9c3bc11d5b87c5b
11+
RxCocoa: a2baaf3462b989559a51dce59d78fbebb8fe0afa
12+
RxSwift: 829b2843e9eddc77a02cb3f5117f0d55f8f646f1
1313

14-
PODFILE CHECKSUM: 0690f6c5e49b45876a70df8d8bd5d011ee043afc
14+
PODFILE CHECKSUM: aa7efef7446c5f9aba76c340621bcd059f388ca8
1515

16-
COCOAPODS: 1.0.0.beta.3
16+
COCOAPODS: 1.0.0.beta.6

0 commit comments

Comments
 (0)