Skip to content

Commit 08b8f51

Browse files
gunterhagermbuchetics
authored andcommitted
Fallback delegate improvements (#9)
* Implemented first version of UIScrollViewDelegate support. * Implemented forwarding target for fallback delegate.
1 parent 85d6a70 commit 08b8f51

4 files changed

Lines changed: 50 additions & 7 deletions

File tree

DataSource/DataSource.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,31 @@ public class DataSource: NSObject {
7272
public var performAction: ((RowType, Selector, Any?, IndexPath) -> Void)? = nil
7373
public var canFocus: ((RowType, IndexPath) -> Bool)? = nil
7474

75-
public var fallbackDelegate: UITableViewDelegate? = nil
76-
7775
// MARK: UITableViewDataSourcePrefetching
7876

7977
public var prefetchRows: (([IndexPath]) -> Void)? = nil
8078
public var cancelPrefetching: (([IndexPath]) -> Void)? = nil
8179

8280
public var fallbackDataSourcePrefetching: UITableViewDataSourcePrefetching? = nil
8381

82+
// MARK: Fallback delegate
83+
84+
/// Fallback used when DataSource doesn't handle delegate method itself.
85+
/// - Note: The fallback delegate needs to be set *before* setting the table view's delegate, otherwise certain delegate methods will never be called.
86+
public var fallbackDelegate: UITableViewDelegate? = nil
87+
88+
public override func forwardingTarget(for aSelector: Selector!) -> Any? {
89+
return fallbackDelegate
90+
}
91+
92+
public override func responds(to aSelector: Selector!) -> Bool {
93+
if super.responds(to: aSelector) {
94+
return true
95+
} else {
96+
return fallbackDelegate?.responds(to: aSelector) ?? false
97+
}
98+
}
99+
84100
// MARK: Additional
85101

86102
public var isRowHidden: ((RowType, IndexPath) -> Bool)? = nil

Example/Storyboards/Base.lproj/Main.storyboard

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Omf-OH-dPB">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Omf-OH-dPB">
33
<device id="retina4_7" orientation="portrait">
44
<adaptation id="fullscreen"/>
55
</device>
66
<dependencies>
77
<deployment identifier="iOS"/>
8-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
8+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
99
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
1010
</dependencies>
1111
<scenes>
@@ -100,7 +100,7 @@
100100
<scene sceneID="S09-Cn-Mdc">
101101
<objects>
102102
<tableViewController storyboardIdentifier="RandomPersonsViewController" title="Persons" id="6py-Jf-HCI" customClass="RandomPersonsViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
103-
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" allowsSelection="NO" rowHeight="60" sectionHeaderHeight="28" sectionFooterHeight="28" id="35F-CF-MSq">
103+
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="60" sectionHeaderHeight="28" sectionFooterHeight="28" id="35F-CF-MSq">
104104
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
105105
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
106106
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
@@ -109,7 +109,7 @@
109109
<rect key="frame" x="0.0" y="28" width="375" height="60"/>
110110
<autoresizingMask key="autoresizingMask"/>
111111
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="t2E-sf-irZ" id="IRY-tD-Gec">
112-
<rect key="frame" x="0.0" y="0.0" width="375" height="59"/>
112+
<rect key="frame" x="0.0" y="0.0" width="375" height="60"/>
113113
<autoresizingMask key="autoresizingMask"/>
114114
<subviews>
115115
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="wUN-ek-B9H">

Example/ViewControllers/Examples/RandomPersonsViewController.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,24 @@ class RandomPersonsViewController: UITableViewController {
1717
DataSource(
1818
cellDescriptors: [
1919
PersonCell.descriptor
20+
.didSelect { (item, indexPath) in
21+
print("\(item.firstName) \(item.lastName) selected")
22+
return .deselect
23+
}
2024
],
2125
sectionDescriptors: [
2226
SectionDescriptor<String>()
2327
.header { (title, _) in
2428
.title(title)
25-
}
29+
}
2630
])
2731
}()
2832

2933
override func viewDidLoad() {
3034
super.viewDidLoad()
3135

36+
dataSource.fallbackDelegate = self
37+
3238
tableView.dataSource = dataSource
3339
tableView.delegate = dataSource
3440

@@ -63,6 +69,16 @@ class RandomPersonsViewController: UITableViewController {
6369
}
6470
}
6571

72+
// MARK: - Scroll view delegate
73+
74+
extension RandomPersonsViewController {
75+
76+
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
77+
print("Scrolled: \(scrollView.contentOffset.y)")
78+
}
79+
80+
}
81+
6682
// MARK: - Person
6783

6884
struct Person {

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,17 @@ dataSource.fallbackDataSource = self
210210

211211
Using these fallback mechanisms you can choose which parts of `DataSource` you want to use in your specific use case. For example, you could use it to setup and configure all your cells, animate changes between datasets but keep your existing `UITableViewDelegate` code.
212212

213+
The `fallbackDelegate` can be used to implement methods that don't belong to `DataSource`, like e.g. `UIScrollViewDelegate` methods. You should take extra care that the fallback delegate needs to be set *before* setting the table view delegate, otherwise certain delegate methods will never be called by `UIKit`.
214+
215+
```swift
216+
// Always set the fallback before setting the table view delegate
217+
dataSource.fallbackDelegate = self
218+
tableView.dataSource = dataSource
219+
tableView.delegate = dataSource
220+
```
221+
222+
223+
213224
## Version Compatibility
214225

215226
Current Swift compatibility breakdown:

0 commit comments

Comments
 (0)