Fixed navigation to detail screen
This commit is contained in:
parent
9d1efd8d0d
commit
734fbc5bc0
@ -35,10 +35,6 @@
|
|||||||
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7924001D3300CBFE6E /* CheckController.swift */; };
|
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7924001D3300CBFE6E /* CheckController.swift */; };
|
||||||
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; };
|
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; };
|
||||||
7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7F2401803A00CBFE6E /* Vehicle.swift */; };
|
7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7F2401803A00CBFE6E /* Vehicle.swift */; };
|
||||||
7A530B85240180CC00CBFE6E /* RxCollectionViewRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B81240180CC00CBFE6E /* RxCollectionViewRealmDataSource.swift */; };
|
|
||||||
7A530B86240180CC00CBFE6E /* RealmBindObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B82240180CC00CBFE6E /* RealmBindObserver.swift */; };
|
|
||||||
7A530B87240180CC00CBFE6E /* Reactive+RxRealmDataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B83240180CC00CBFE6E /* Reactive+RxRealmDataSources.swift */; };
|
|
||||||
7A530B88240180CC00CBFE6E /* RxTableViewRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B84240180CC00CBFE6E /* RxTableViewRealmDataSource.swift */; };
|
|
||||||
7A530B8B240181F500CBFE6E /* RxRealm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A530B8A240181F500CBFE6E /* RxRealm */; };
|
7A530B8B240181F500CBFE6E /* RxRealm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A530B8A240181F500CBFE6E /* RxRealm */; };
|
||||||
7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6DD902242BF4A5009DE740 /* PlateView.swift */; };
|
7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6DD902242BF4A5009DE740 /* PlateView.swift */; };
|
||||||
7A6DD90824329144009DE740 /* CenterTextLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6DD90724329144009DE740 /* CenterTextLayer.swift */; };
|
7A6DD90824329144009DE740 /* CenterTextLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6DD90724329144009DE740 /* CenterTextLayer.swift */; };
|
||||||
@ -76,10 +72,6 @@
|
|||||||
7A530B7924001D3300CBFE6E /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = "<group>"; };
|
7A530B7924001D3300CBFE6E /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = "<group>"; };
|
||||||
7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleCell.swift; sourceTree = "<group>"; };
|
7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleCell.swift; sourceTree = "<group>"; };
|
||||||
7A530B7F2401803A00CBFE6E /* Vehicle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vehicle.swift; sourceTree = "<group>"; };
|
7A530B7F2401803A00CBFE6E /* Vehicle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vehicle.swift; sourceTree = "<group>"; };
|
||||||
7A530B81240180CC00CBFE6E /* RxCollectionViewRealmDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxCollectionViewRealmDataSource.swift; sourceTree = "<group>"; };
|
|
||||||
7A530B82240180CC00CBFE6E /* RealmBindObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBindObserver.swift; sourceTree = "<group>"; };
|
|
||||||
7A530B83240180CC00CBFE6E /* Reactive+RxRealmDataSources.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Reactive+RxRealmDataSources.swift"; sourceTree = "<group>"; };
|
|
||||||
7A530B84240180CC00CBFE6E /* RxTableViewRealmDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTableViewRealmDataSource.swift; sourceTree = "<group>"; };
|
|
||||||
7A6DD902242BF4A5009DE740 /* PlateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlateView.swift; sourceTree = "<group>"; };
|
7A6DD902242BF4A5009DE740 /* PlateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlateView.swift; sourceTree = "<group>"; };
|
||||||
7A6DD90724329144009DE740 /* CenterTextLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CenterTextLayer.swift; sourceTree = "<group>"; };
|
7A6DD90724329144009DE740 /* CenterTextLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CenterTextLayer.swift; sourceTree = "<group>"; };
|
||||||
7A6DD90924329541009DE740 /* RoadNumbers2.0.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = RoadNumbers2.0.otf; sourceTree = "<group>"; };
|
7A6DD90924329541009DE740 /* RoadNumbers2.0.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = RoadNumbers2.0.otf; sourceTree = "<group>"; };
|
||||||
@ -173,7 +165,6 @@
|
|||||||
7A11472C23FECA3E00B424AF /* ThirdParty */ = {
|
7A11472C23FECA3E00B424AF /* ThirdParty */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
7A530B7B24017DED00CBFE6E /* RxRealmDataSources */,
|
|
||||||
7A6DD90724329144009DE740 /* CenterTextLayer.swift */,
|
7A6DD90724329144009DE740 /* CenterTextLayer.swift */,
|
||||||
);
|
);
|
||||||
path = ThirdParty;
|
path = ThirdParty;
|
||||||
@ -209,17 +200,6 @@
|
|||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
7A530B7B24017DED00CBFE6E /* RxRealmDataSources */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
7A530B83240180CC00CBFE6E /* Reactive+RxRealmDataSources.swift */,
|
|
||||||
7A530B82240180CC00CBFE6E /* RealmBindObserver.swift */,
|
|
||||||
7A530B81240180CC00CBFE6E /* RxCollectionViewRealmDataSource.swift */,
|
|
||||||
7A530B84240180CC00CBFE6E /* RxTableViewRealmDataSource.swift */,
|
|
||||||
);
|
|
||||||
path = RxRealmDataSources;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
7A530B7C24017FBE00CBFE6E /* Cells */ = {
|
7A530B7C24017FBE00CBFE6E /* Cells */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -375,7 +355,6 @@
|
|||||||
files = (
|
files = (
|
||||||
7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */,
|
7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */,
|
||||||
7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */,
|
7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */,
|
||||||
7A530B86240180CC00CBFE6E /* RealmBindObserver.swift in Sources */,
|
|
||||||
7A6DD90824329144009DE740 /* CenterTextLayer.swift in Sources */,
|
7A6DD90824329144009DE740 /* CenterTextLayer.swift in Sources */,
|
||||||
7A6DD90C24335A6D009DE740 /* FlagLayer.swift in Sources */,
|
7A6DD90C24335A6D009DE740 /* FlagLayer.swift in Sources */,
|
||||||
7A6DD90E24337930009DE740 /* PlateNumber.swift in Sources */,
|
7A6DD90E24337930009DE740 /* PlateNumber.swift in Sources */,
|
||||||
@ -387,14 +366,11 @@
|
|||||||
7A7547DD2403180A004E8406 /* SectionHeader.swift in Sources */,
|
7A7547DD2403180A004E8406 /* SectionHeader.swift in Sources */,
|
||||||
7AF58D58240309CA00CE01A0 /* VehicleTextParamCell.swift in Sources */,
|
7AF58D58240309CA00CE01A0 /* VehicleTextParamCell.swift in Sources */,
|
||||||
7A11474723FF2AA500B424AF /* User.swift in Sources */,
|
7A11474723FF2AA500B424AF /* User.swift in Sources */,
|
||||||
7A530B88240180CC00CBFE6E /* RxTableViewRealmDataSource.swift in Sources */,
|
|
||||||
7A11471623FDEB2A00B424AF /* MainSplitController.swift in Sources */,
|
7A11471623FDEB2A00B424AF /* MainSplitController.swift in Sources */,
|
||||||
7AF58D3124029E1000CE01A0 /* VehicleHeaderCell.swift in Sources */,
|
7AF58D3124029E1000CE01A0 /* VehicleHeaderCell.swift in Sources */,
|
||||||
7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */,
|
7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */,
|
||||||
7A530B85240180CC00CBFE6E /* RxCollectionViewRealmDataSource.swift in Sources */,
|
|
||||||
7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */,
|
7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */,
|
||||||
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */,
|
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */,
|
||||||
7A530B87240180CC00CBFE6E /* Reactive+RxRealmDataSources.swift in Sources */,
|
|
||||||
7A11474423FF06CA00B424AF /* Api.swift in Sources */,
|
7A11474423FF06CA00B424AF /* Api.swift in Sources */,
|
||||||
7A05161A2414FF0900FC55AC /* DateSection.swift in Sources */,
|
7A05161A2414FF0900FC55AC /* DateSection.swift in Sources */,
|
||||||
7A11474B23FF368B00B424AF /* Settings.swift in Sources */,
|
7A11474B23FF368B00B424AF /* Settings.swift in Sources */,
|
||||||
|
|||||||
@ -280,35 +280,42 @@
|
|||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="3ON-lr-UlV" id="IGw-UK-ebp">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="3ON-lr-UlV" id="IGw-UK-ebp">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="85"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="85"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="top" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="prz-7c-HiS">
|
|
||||||
<rect key="frame" x="8" y="8" width="359" height="69"/>
|
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Kia (JF) Optima" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="h3N-1o-J20">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Kia (JF) Optima" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="h3N-1o-J20">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="124" height="21"/>
|
<rect key="frame" x="8" y="8" width="124" height="21"/>
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="VHX-o0-3BP" customClass="PlateView" customModule="AutoCat" customModuleProvider="target">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rKr-3e-WYb">
|
||||||
<rect key="frame" x="0.0" y="29" width="359" height="40"/>
|
<rect key="frame" x="334" y="8" width="33" height="16"/>
|
||||||
|
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
|
||||||
|
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VHX-o0-3BP" customClass="PlateView" customModule="AutoCat" customModuleProvider="target">
|
||||||
|
<rect key="frame" x="8" y="37" width="317" height="40"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="40" id="vzo-oF-mWb"/>
|
<constraint firstAttribute="height" constant="40" id="vzo-oF-mWb"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
</subviews>
|
</subviews>
|
||||||
</stackView>
|
|
||||||
</subviews>
|
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="trailing" secondItem="prz-7c-HiS" secondAttribute="trailing" constant="8" id="42F-cD-DAn"/>
|
<constraint firstAttribute="bottom" secondItem="VHX-o0-3BP" secondAttribute="bottom" constant="8" id="7hb-rB-XFk"/>
|
||||||
<constraint firstItem="prz-7c-HiS" firstAttribute="top" secondItem="IGw-UK-ebp" secondAttribute="top" constant="8" id="W9V-oe-unX"/>
|
<constraint firstItem="rKr-3e-WYb" firstAttribute="top" secondItem="IGw-UK-ebp" secondAttribute="top" constant="8" id="Aae-DJ-RWv"/>
|
||||||
<constraint firstItem="prz-7c-HiS" firstAttribute="leading" secondItem="IGw-UK-ebp" secondAttribute="leading" constant="8" id="tvA-Ow-u6L"/>
|
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="VHX-o0-3BP" secondAttribute="trailing" constant="8" id="CNo-ir-xoh"/>
|
||||||
<constraint firstAttribute="bottom" secondItem="prz-7c-HiS" secondAttribute="bottom" constant="8" id="v1W-gU-mvW"/>
|
<constraint firstAttribute="trailing" secondItem="rKr-3e-WYb" secondAttribute="trailing" constant="8" id="Efc-w5-0Xo"/>
|
||||||
|
<constraint firstItem="VHX-o0-3BP" firstAttribute="leading" secondItem="IGw-UK-ebp" secondAttribute="leading" constant="8" id="PgR-8A-drv"/>
|
||||||
|
<constraint firstItem="VHX-o0-3BP" firstAttribute="top" secondItem="h3N-1o-J20" secondAttribute="bottom" constant="8" id="U0q-5Z-FxE"/>
|
||||||
|
<constraint firstItem="h3N-1o-J20" firstAttribute="leading" secondItem="IGw-UK-ebp" secondAttribute="leading" constant="8" id="eqF-fX-u0u"/>
|
||||||
|
<constraint firstItem="rKr-3e-WYb" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="h3N-1o-J20" secondAttribute="trailing" constant="8" id="h98-lu-Lji"/>
|
||||||
|
<constraint firstItem="h3N-1o-J20" firstAttribute="top" secondItem="IGw-UK-ebp" secondAttribute="top" constant="8" id="yx2-fR-etv"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
<inset key="separatorInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
<inset key="separatorInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||||
<connections>
|
<connections>
|
||||||
|
<outlet property="date" destination="rKr-3e-WYb" id="TOr-YS-0IE"/>
|
||||||
<outlet property="name" destination="h3N-1o-J20" id="jcM-B4-bEJ"/>
|
<outlet property="name" destination="h3N-1o-J20" id="jcM-B4-bEJ"/>
|
||||||
<outlet property="plate" destination="VHX-o0-3BP" id="D8N-L7-O8b"/>
|
<outlet property="plate" destination="VHX-o0-3BP" id="D8N-L7-O8b"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
|||||||
@ -4,16 +4,22 @@ class VehicleCell: UITableViewCell {
|
|||||||
|
|
||||||
@IBOutlet weak var name: UILabel!
|
@IBOutlet weak var name: UILabel!
|
||||||
@IBOutlet weak var plate: PlateView!
|
@IBOutlet weak var plate: PlateView!
|
||||||
|
@IBOutlet weak var date: UILabel!
|
||||||
|
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
|
||||||
override func awakeFromNib() {
|
override func awakeFromNib() {
|
||||||
super.awakeFromNib()
|
super.awakeFromNib()
|
||||||
|
|
||||||
|
formatter.dateStyle = .short
|
||||||
|
formatter.timeStyle = .short
|
||||||
}
|
}
|
||||||
|
|
||||||
func configure(with vehicle: Vehicle) {
|
func configure(with vehicle: Vehicle) {
|
||||||
self.name.text = vehicle.brand?.name?.original ?? "<unknown>"
|
self.name.text = vehicle.brand?.name?.original ?? "<unknown>"
|
||||||
self.plate.number = PlateNumber(vehicle.number)
|
self.plate.number = PlateNumber(vehicle.number)
|
||||||
self.plate.unrecognized = vehicle.brand == nil
|
self.plate.unrecognized = vehicle.brand == nil
|
||||||
|
self.date.text = formatter.string(from: Date(timeIntervalSince1970: vehicle.addedDate/1000))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,11 +24,6 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
|
|||||||
self.number.delegate = self.maskFieldDelegate
|
self.number.delegate = self.maskFieldDelegate
|
||||||
self.check.isEnabled = false
|
self.check.isEnabled = false
|
||||||
|
|
||||||
// let ds = RxTableViewRealmDataSource<Vehicle>(cellIdentifier: "VehicleCell", cellType: VehicleCell.self) { cell, ip, vehicle in
|
|
||||||
// cell.configure(with: vehicle)
|
|
||||||
// }
|
|
||||||
// ds.headerTitle = "History"
|
|
||||||
|
|
||||||
let ds = RxTableViewSectionedAnimatedDataSource<DateSection<Vehicle>>(configureCell: { dataSource, tableView, indexPath, item in
|
let ds = RxTableViewSectionedAnimatedDataSource<DateSection<Vehicle>>(configureCell: { dataSource, tableView, indexPath, item in
|
||||||
if let cell = tableView.dequeueReusableCell(withIdentifier: "VehicleCell", for: indexPath) as? VehicleCell {
|
if let cell = tableView.dequeueReusableCell(withIdentifier: "VehicleCell", for: indexPath) as? VehicleCell {
|
||||||
cell.configure(with: item)
|
cell.configure(with: item)
|
||||||
@ -42,24 +37,13 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
|
|||||||
return dataSourse.sectionModels[index].header
|
return dataSourse.sectionModels[index].header
|
||||||
}
|
}
|
||||||
|
|
||||||
let realm = try! Realm()
|
self.history.rx.modelSelected(Vehicle.self)
|
||||||
// Observable.changeset(from: realm.objects(Vehicle.self).sorted(byKeyPath: "addedDate", ascending: false))
|
|
||||||
// .bind(to: self.history.rx.realmChanges(ds))
|
|
||||||
// .disposed(by: self.bag)
|
|
||||||
|
|
||||||
self.history.rx.realmModelSelected(Vehicle.self)
|
|
||||||
.subscribe(onNext: self.updateDetailController(with:))
|
.subscribe(onNext: self.updateDetailController(with:))
|
||||||
.disposed(by: self.bag)
|
.disposed(by: self.bag)
|
||||||
|
|
||||||
let now = Date()
|
let now = Date()
|
||||||
let monthStart = now.dateAtStartOf(.month)
|
let monthStart = now.dateAtStartOf(.month)
|
||||||
let weekStart = now.dateAtStartOf(.weekOfMonth)
|
let realm = try! Realm()
|
||||||
|
|
||||||
print("==================================")
|
|
||||||
print("now: \(now)")
|
|
||||||
print("week start: \(weekStart)")
|
|
||||||
print("month start: \(monthStart)")
|
|
||||||
print("==================================")
|
|
||||||
|
|
||||||
Observable.collection(from: realm.objects(Vehicle.self).sorted(byKeyPath: "addedDate", ascending: false)).map { (vehicles: Results<Vehicle>) -> [DateSection<Vehicle>] in
|
Observable.collection(from: realm.objects(Vehicle.self).sorted(byKeyPath: "addedDate", ascending: false)).map { (vehicles: Results<Vehicle>) -> [DateSection<Vehicle>] in
|
||||||
var sections: [TimeInterval: [Vehicle]] = [:]
|
var sections: [TimeInterval: [Vehicle]] = [:]
|
||||||
@ -94,6 +78,13 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
|
|||||||
self.navigationController?.setNavigationBarHidden(true, animated: false)
|
self.navigationController?.setNavigationBarHidden(true, animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewWillDisappear(_ animated: Bool) {
|
||||||
|
super.viewWillDisappear(animated)
|
||||||
|
if let index = self.history.indexPathForSelectedRow {
|
||||||
|
self.history.deselectRow(at: index, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@IBAction func checkTapped(_ sender: UIButton) {
|
@IBAction func checkTapped(_ sender: UIButton) {
|
||||||
guard let number = self.number.text else { return }
|
guard let number = self.number.text else { return }
|
||||||
|
|
||||||
@ -101,6 +92,7 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
|
|||||||
|
|
||||||
self.number.resignFirstResponder()
|
self.number.resignFirstResponder()
|
||||||
self.number.text = nil
|
self.number.text = nil
|
||||||
|
self.check.isEnabled = false
|
||||||
SVProgressHUD.show()
|
SVProgressHUD.show()
|
||||||
Api.checkVehicle(by: numberNormalized)
|
Api.checkVehicle(by: numberNormalized)
|
||||||
.observeOn(MainScheduler.instance)
|
.observeOn(MainScheduler.instance)
|
||||||
|
|||||||
@ -1,113 +0,0 @@
|
|||||||
//
|
|
||||||
// RxRealm extensions
|
|
||||||
//
|
|
||||||
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
|
|
||||||
// Check the LICENSE file for details
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
import RealmSwift
|
|
||||||
import RxSwift
|
|
||||||
import RxCocoa
|
|
||||||
import RxRealm
|
|
||||||
|
|
||||||
#if os(iOS)
|
|
||||||
// MARK: - iOS / UIKit
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
extension Reactive where Base: UITableView {
|
|
||||||
|
|
||||||
public func realmChanges<E>(_ dataSource: RxTableViewRealmDataSource<E>)
|
|
||||||
-> RealmBindObserver<E, AnyRealmCollection<E>, RxTableViewRealmDataSource<E>> {
|
|
||||||
|
|
||||||
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
|
|
||||||
if ds.tableView == nil {
|
|
||||||
ds.tableView = self.base
|
|
||||||
}
|
|
||||||
ds.tableView?.dataSource = ds
|
|
||||||
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func realmModelSelected<E>(_ modelType: E.Type) -> ControlEvent<E> where E: RealmSwift.Object {
|
|
||||||
|
|
||||||
let source: Observable<E> = self.itemSelected.flatMap { [weak view = self.base as UITableView] indexPath -> Observable<E> in
|
|
||||||
guard let view = view, let ds = view.dataSource as? RxTableViewRealmDataSource<E> else {
|
|
||||||
return Observable.empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
return Observable.just(ds.model(at: indexPath))
|
|
||||||
}
|
|
||||||
|
|
||||||
return ControlEvent(events: source)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Reactive where Base: UICollectionView {
|
|
||||||
|
|
||||||
public func realmChanges<E>(_ dataSource: RxCollectionViewRealmDataSource<E>)
|
|
||||||
-> RealmBindObserver<E, AnyRealmCollection<E>, RxCollectionViewRealmDataSource<E>> {
|
|
||||||
|
|
||||||
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
|
|
||||||
if ds.collectionView == nil {
|
|
||||||
ds.collectionView = self.base
|
|
||||||
}
|
|
||||||
ds.collectionView?.dataSource = ds
|
|
||||||
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func realmModelSelected<E>(_ modelType: E.Type) -> ControlEvent<E> where E: RealmSwift.Object {
|
|
||||||
|
|
||||||
let source: Observable<E> = self.itemSelected.flatMap { [weak view = self.base as UICollectionView] indexPath -> Observable<E> in
|
|
||||||
guard let view = view, let ds = view.dataSource as? RxCollectionViewRealmDataSource<E> else {
|
|
||||||
return Observable.empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
return Observable.just(ds.model(at: indexPath))
|
|
||||||
}
|
|
||||||
|
|
||||||
return ControlEvent(events: source)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#elseif os(OSX)
|
|
||||||
// MARK: - macOS / Cocoa
|
|
||||||
|
|
||||||
import Cocoa
|
|
||||||
extension Reactive where Base: NSTableView {
|
|
||||||
|
|
||||||
public func realmChanges<E>(_ dataSource: RxTableViewRealmDataSource<E>)
|
|
||||||
-> RealmBindObserver<E, AnyRealmCollection<E>, RxTableViewRealmDataSource<E>> {
|
|
||||||
|
|
||||||
base.delegate = dataSource
|
|
||||||
base.dataSource = dataSource
|
|
||||||
|
|
||||||
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
|
|
||||||
if dataSource.tableView == nil {
|
|
||||||
dataSource.tableView = self.base
|
|
||||||
}
|
|
||||||
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Reactive where Base: NSCollectionView {
|
|
||||||
|
|
||||||
public func realmChanges<E>(_ dataSource: RxCollectionViewRealmDataSource<E>)
|
|
||||||
-> RealmBindObserver<E, AnyRealmCollection<E>, RxCollectionViewRealmDataSource<E>> {
|
|
||||||
|
|
||||||
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
|
|
||||||
if ds.collectionView == nil {
|
|
||||||
ds.collectionView = self.base
|
|
||||||
}
|
|
||||||
ds.collectionView?.dataSource = ds
|
|
||||||
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
//
|
|
||||||
// RxRealm extensions
|
|
||||||
//
|
|
||||||
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
|
|
||||||
// Check the LICENSE file for details
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
import RealmSwift
|
|
||||||
import RxSwift
|
|
||||||
import RxCocoa
|
|
||||||
import RxRealm
|
|
||||||
|
|
||||||
public class RealmBindObserver<O: Object, C: RealmCollection, DS>: ObserverType {
|
|
||||||
typealias BindingType = (DS, C, RealmChangeset?) -> Void
|
|
||||||
public typealias E = (C, RealmChangeset?)
|
|
||||||
|
|
||||||
let dataSource: DS
|
|
||||||
let binding: BindingType
|
|
||||||
|
|
||||||
init(dataSource: DS, binding: @escaping BindingType) {
|
|
||||||
self.dataSource = dataSource
|
|
||||||
self.binding = binding
|
|
||||||
}
|
|
||||||
|
|
||||||
public func on(_ event: Event<E>) {
|
|
||||||
switch event {
|
|
||||||
case .next(let element):
|
|
||||||
binding(dataSource, element.0, element.1)
|
|
||||||
case .error:
|
|
||||||
return
|
|
||||||
case .completed:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func asObserver() -> AnyObserver<E> {
|
|
||||||
return AnyObserver(eventHandler: on)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,210 +0,0 @@
|
|||||||
//
|
|
||||||
// RxRealm extensions
|
|
||||||
//
|
|
||||||
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
|
|
||||||
// Check the LICENSE file for details
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
import RealmSwift
|
|
||||||
import RxSwift
|
|
||||||
import RxCocoa
|
|
||||||
import RxRealm
|
|
||||||
|
|
||||||
#if os(iOS)
|
|
||||||
// MARK: - iOS / UIKit
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
public typealias CollectionCellFactory<E: Object> = (RxCollectionViewRealmDataSource<E>, UICollectionView, IndexPath, E) -> UICollectionViewCell
|
|
||||||
public typealias CollectionCellConfig<E: Object, CellType: UICollectionViewCell> = (CellType, IndexPath, E) -> Void
|
|
||||||
|
|
||||||
open class RxCollectionViewRealmDataSource <E: Object>: NSObject, UICollectionViewDataSource {
|
|
||||||
private var items: AnyRealmCollection<E>?
|
|
||||||
|
|
||||||
// MARK: - Configuration
|
|
||||||
|
|
||||||
public var collectionView: UICollectionView?
|
|
||||||
public var animated = true
|
|
||||||
|
|
||||||
// MARK: - Init
|
|
||||||
public let cellIdentifier: String
|
|
||||||
public let cellFactory: CollectionCellFactory<E>
|
|
||||||
|
|
||||||
public init(cellIdentifier: String, cellFactory: @escaping CollectionCellFactory<E>) {
|
|
||||||
self.cellIdentifier = cellIdentifier
|
|
||||||
self.cellFactory = cellFactory
|
|
||||||
}
|
|
||||||
|
|
||||||
public init<CellType>(cellIdentifier: String, cellType: CellType.Type, cellConfig: @escaping CollectionCellConfig<E, CellType>) where CellType: UICollectionViewCell {
|
|
||||||
self.cellIdentifier = cellIdentifier
|
|
||||||
self.cellFactory = {ds, cv, ip, model in
|
|
||||||
let cell = cv.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: ip) as! CellType
|
|
||||||
cellConfig(cell, ip, model)
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Data access
|
|
||||||
public func model(at indexPath: IndexPath) -> E {
|
|
||||||
return items![indexPath.row]
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - UICollectionViewDataSource protocol
|
|
||||||
public func numberOfSections(in collectionView: UICollectionView) -> Int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
|
||||||
return items?.count ?? 0
|
|
||||||
}
|
|
||||||
|
|
||||||
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
|
||||||
return cellFactory(self, collectionView, indexPath, items![indexPath.row])
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Applying changeset to the collection view
|
|
||||||
private let fromRow = {(row: Int) in return IndexPath(row: row, section: 0)}
|
|
||||||
|
|
||||||
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
|
|
||||||
if self.items == nil {
|
|
||||||
self.items = items
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let collectionView = collectionView else {
|
|
||||||
fatalError("You have to bind a collection view to the data source.")
|
|
||||||
}
|
|
||||||
|
|
||||||
guard animated else {
|
|
||||||
collectionView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let changes = changes else {
|
|
||||||
collectionView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let lastItemCount = collectionView.numberOfItems(inSection: 0)
|
|
||||||
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
|
|
||||||
collectionView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
collectionView.performBatchUpdates({[unowned self] in
|
|
||||||
collectionView.deleteItems(at: changes.deleted.map(self.fromRow))
|
|
||||||
collectionView.reloadItems(at: changes.updated.map(self.fromRow))
|
|
||||||
collectionView.insertItems(at: changes.inserted.map(self.fromRow))
|
|
||||||
}, completion: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#elseif os(OSX)
|
|
||||||
// MARK: - macOS / Cocoa
|
|
||||||
|
|
||||||
import Cocoa
|
|
||||||
|
|
||||||
public typealias CollectionItemFactory<E: Object> = (RxCollectionViewRealmDataSource<E>, NSCollectionView, IndexPath, E) -> NSCollectionViewItem
|
|
||||||
public typealias CollectionItemConfig<E: Object, ItemType: NSCollectionViewItem> = (ItemType, IndexPath, E) -> Void
|
|
||||||
|
|
||||||
open class RxCollectionViewRealmDataSource <E: Object>: NSObject, NSCollectionViewDataSource {
|
|
||||||
|
|
||||||
private var items: AnyRealmCollection<E>?
|
|
||||||
|
|
||||||
// MARK: - Configuration
|
|
||||||
|
|
||||||
public var collectionView: NSCollectionView?
|
|
||||||
public var animated = true
|
|
||||||
|
|
||||||
// MARK: - Init
|
|
||||||
public let itemIdentifier: String
|
|
||||||
public let itemFactory: CollectionItemFactory<E>
|
|
||||||
|
|
||||||
public weak var delegate: NSCollectionViewDelegate?
|
|
||||||
public weak var dataSource: NSCollectionViewDataSource?
|
|
||||||
|
|
||||||
public init(itemIdentifier: String, itemFactory: @escaping CollectionItemFactory<E>) {
|
|
||||||
self.itemIdentifier = itemIdentifier
|
|
||||||
self.itemFactory = itemFactory
|
|
||||||
}
|
|
||||||
|
|
||||||
public init<ItemType>(itemIdentifier: String, itemType: ItemType.Type, itemConfig: @escaping CollectionItemConfig<E, ItemType>) where ItemType: NSCollectionViewItem {
|
|
||||||
self.itemIdentifier = itemIdentifier
|
|
||||||
self.itemFactory = { ds, cv, ip, model in
|
|
||||||
let item = cv.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: itemIdentifier), for: ip) as! ItemType
|
|
||||||
itemConfig(item, ip, model)
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - NSCollectionViewDataSource protocol
|
|
||||||
public func numberOfSections(in collectionView: NSCollectionView) -> Int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
public func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
|
|
||||||
return items?.count ?? 0
|
|
||||||
}
|
|
||||||
|
|
||||||
@available(OSX 10.11, *)
|
|
||||||
public func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
|
|
||||||
return itemFactory(self, collectionView, indexPath, items![indexPath.item])
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Proxy unimplemented data source and delegate methods
|
|
||||||
open override func responds(to aSelector: Selector!) -> Bool {
|
|
||||||
if RxCollectionViewRealmDataSource.instancesRespond(to: aSelector) {
|
|
||||||
return true
|
|
||||||
} else if let delegate = delegate {
|
|
||||||
return delegate.responds(to: aSelector)
|
|
||||||
} else if let dataSource = dataSource {
|
|
||||||
return dataSource.responds(to: aSelector)
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open override func forwardingTarget(for aSelector: Selector!) -> Any? {
|
|
||||||
return delegate ?? dataSource
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Applying changeset to the collection view
|
|
||||||
private let fromRow = {(row: Int) in return IndexPath(item: row, section: 0)}
|
|
||||||
|
|
||||||
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
|
|
||||||
if self.items == nil {
|
|
||||||
self.items = items
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let collectionView = collectionView else {
|
|
||||||
fatalError("You have to bind a collection view to the data source.")
|
|
||||||
}
|
|
||||||
|
|
||||||
guard animated else {
|
|
||||||
collectionView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let changes = changes else {
|
|
||||||
collectionView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let lastItemCount = collectionView.numberOfItems(inSection: 0)
|
|
||||||
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
|
|
||||||
collectionView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
collectionView.performBatchUpdates({[unowned self] in
|
|
||||||
//TODO: this should be animated, but doesn't seem to be?
|
|
||||||
collectionView.animator().deleteItems(at: Set(changes.deleted.map(self.fromRow)))
|
|
||||||
collectionView.animator().reloadItems(at: Set(changes.updated.map(self.fromRow)))
|
|
||||||
collectionView.animator().insertItems(at: Set(changes.inserted.map(self.fromRow)))
|
|
||||||
}, completionHandler: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,223 +0,0 @@
|
|||||||
//
|
|
||||||
// RxRealm extensions
|
|
||||||
//
|
|
||||||
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
|
|
||||||
// Check the LICENSE file for details
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
import RealmSwift
|
|
||||||
import RxSwift
|
|
||||||
import RxCocoa
|
|
||||||
import RxRealm
|
|
||||||
|
|
||||||
#if os(iOS)
|
|
||||||
// MARK: - iOS / UIKit
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
public typealias TableCellFactory<E: Object> = (RxTableViewRealmDataSource<E>, UITableView, IndexPath, E) -> UITableViewCell
|
|
||||||
public typealias TableCellConfig<E: Object, CellType: UITableViewCell> = (CellType, IndexPath, E) -> Void
|
|
||||||
|
|
||||||
open class RxTableViewRealmDataSource<E: Object>: NSObject, UITableViewDataSource {
|
|
||||||
|
|
||||||
private var items: AnyRealmCollection<E>?
|
|
||||||
|
|
||||||
// MARK: - Configuration
|
|
||||||
|
|
||||||
public var tableView: UITableView?
|
|
||||||
public var animated = true
|
|
||||||
public var rowAnimations = (
|
|
||||||
insert: UITableView.RowAnimation.automatic,
|
|
||||||
update: UITableView.RowAnimation.automatic,
|
|
||||||
delete: UITableView.RowAnimation.automatic)
|
|
||||||
|
|
||||||
public var headerTitle: String?
|
|
||||||
public var footerTitle: String?
|
|
||||||
|
|
||||||
// MARK: - Init
|
|
||||||
public let cellIdentifier: String
|
|
||||||
public let cellFactory: TableCellFactory<E>
|
|
||||||
|
|
||||||
public init(cellIdentifier: String, cellFactory: @escaping TableCellFactory<E>) {
|
|
||||||
self.cellIdentifier = cellIdentifier
|
|
||||||
self.cellFactory = cellFactory
|
|
||||||
}
|
|
||||||
|
|
||||||
public init<CellType>(cellIdentifier: String, cellType: CellType.Type, cellConfig: @escaping TableCellConfig<E, CellType>) where CellType: UITableViewCell {
|
|
||||||
self.cellIdentifier = cellIdentifier
|
|
||||||
self.cellFactory = {ds, tv, ip, model in
|
|
||||||
let cell = tv.dequeueReusableCell(withIdentifier: cellIdentifier, for: ip) as! CellType
|
|
||||||
cellConfig(cell, ip, model)
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Data access
|
|
||||||
public func model(at indexPath: IndexPath) -> E {
|
|
||||||
return items![indexPath.row]
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - UITableViewDataSource protocol
|
|
||||||
public func numberOfSections(in tableView: UITableView) -> Int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
||||||
return items?.count ?? 0
|
|
||||||
}
|
|
||||||
|
|
||||||
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
||||||
return cellFactory(self, tableView, indexPath, items![indexPath.row])
|
|
||||||
}
|
|
||||||
|
|
||||||
public func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
|
||||||
return headerTitle
|
|
||||||
}
|
|
||||||
|
|
||||||
public func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
|
||||||
return footerTitle
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Applying changeset to the table view
|
|
||||||
private let fromRow = {(row: Int) in return IndexPath(row: row, section: 0)}
|
|
||||||
|
|
||||||
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
|
|
||||||
if self.items == nil {
|
|
||||||
self.items = items
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let tableView = tableView else {
|
|
||||||
fatalError("You have to bind a table view to the data source.")
|
|
||||||
}
|
|
||||||
|
|
||||||
guard animated else {
|
|
||||||
tableView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let changes = changes else {
|
|
||||||
tableView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let lastItemCount = tableView.numberOfRows(inSection: 0)
|
|
||||||
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
|
|
||||||
tableView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tableView.beginUpdates()
|
|
||||||
tableView.deleteRows(at: changes.deleted.map(fromRow), with: rowAnimations.delete)
|
|
||||||
tableView.insertRows(at: changes.inserted.map(fromRow), with: rowAnimations.insert)
|
|
||||||
tableView.reloadRows(at: changes.updated.map(fromRow), with: rowAnimations.update)
|
|
||||||
tableView.endUpdates()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#elseif os(OSX)
|
|
||||||
// MARK: - macOS / Cocoa
|
|
||||||
|
|
||||||
import Cocoa
|
|
||||||
|
|
||||||
public typealias TableCellFactory<E: Object> = (RxTableViewRealmDataSource<E>, NSTableView, Int, E) -> NSTableCellView
|
|
||||||
public typealias TableCellConfig<E: Object, CellType: NSTableCellView> = (CellType, Int, E) -> Void
|
|
||||||
|
|
||||||
open class RxTableViewRealmDataSource<E: Object>: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
|
||||||
|
|
||||||
private var items: AnyRealmCollection<E>?
|
|
||||||
|
|
||||||
// MARK: - Configuration
|
|
||||||
|
|
||||||
public var tableView: NSTableView?
|
|
||||||
public var animated = true
|
|
||||||
public var rowAnimations = (
|
|
||||||
insert: NSTableView.AnimationOptions.effectFade,
|
|
||||||
update: NSTableView.AnimationOptions.effectFade,
|
|
||||||
delete: NSTableView.AnimationOptions.effectFade)
|
|
||||||
|
|
||||||
public weak var delegate: NSTableViewDelegate?
|
|
||||||
public weak var dataSource: NSTableViewDataSource?
|
|
||||||
|
|
||||||
// MARK: - Init
|
|
||||||
public let cellIdentifier: String
|
|
||||||
public let cellFactory: TableCellFactory<E>
|
|
||||||
|
|
||||||
public init(cellIdentifier: String, cellFactory: @escaping TableCellFactory<E>) {
|
|
||||||
self.cellIdentifier = cellIdentifier
|
|
||||||
self.cellFactory = cellFactory
|
|
||||||
}
|
|
||||||
|
|
||||||
public init<CellType>(cellIdentifier: String, cellType: CellType.Type, cellConfig: @escaping TableCellConfig<E, CellType>) where CellType: NSTableCellView {
|
|
||||||
self.cellIdentifier = cellIdentifier
|
|
||||||
self.cellFactory = { ds, tv, row, model in
|
|
||||||
let cell = tv.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellIdentifier), owner: tv) as! CellType
|
|
||||||
cellConfig(cell, row, model)
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - UITableViewDataSource protocol
|
|
||||||
public func numberOfRows(in tableView: NSTableView) -> Int {
|
|
||||||
return items?.count ?? 0
|
|
||||||
}
|
|
||||||
|
|
||||||
public func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
|
||||||
return cellFactory(self, tableView, row, items![row])
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Proxy unimplemented data source and delegate methods
|
|
||||||
open override func responds(to aSelector: Selector!) -> Bool {
|
|
||||||
if RxTableViewRealmDataSource.instancesRespond(to: aSelector) {
|
|
||||||
return true
|
|
||||||
} else if let delegate = delegate {
|
|
||||||
return delegate.responds(to: aSelector)
|
|
||||||
} else if let dataSource = dataSource {
|
|
||||||
return dataSource.responds(to: aSelector)
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open override func forwardingTarget(for aSelector: Selector!) -> Any? {
|
|
||||||
return delegate ?? dataSource
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Applying changeset to the table view
|
|
||||||
private let fromRow = {(row: Int) in return IndexPath(item: row, section: 0)}
|
|
||||||
|
|
||||||
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
|
|
||||||
if self.items == nil {
|
|
||||||
self.items = items
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let tableView = tableView else {
|
|
||||||
fatalError("You have to bind a table view to the data source.")
|
|
||||||
}
|
|
||||||
|
|
||||||
guard animated else {
|
|
||||||
tableView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let changes = changes else {
|
|
||||||
tableView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let lastItemCount = tableView.numberOfRows
|
|
||||||
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
|
|
||||||
tableView.reloadData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tableView.beginUpdates()
|
|
||||||
tableView.removeRows(at: IndexSet(changes.deleted), withAnimation: rowAnimations.delete)
|
|
||||||
tableView.insertRows(at: IndexSet(changes.inserted), withAnimation: rowAnimations.insert)
|
|
||||||
tableView.reloadData(forRowIndexes: IndexSet(changes.updated), columnIndexes: IndexSet([0]))
|
|
||||||
tableView.endUpdates()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Loading…
Reference in New Issue
Block a user