mirror of
https://github.com/ReactiveX/RxSwift.git
synced 2024-10-05 06:27:29 +03:00
Adds SectionedViewDataSourceType
and rx_modelDeselected
, rx_deselectedItemAtIndexPath
for UICollectionView
, and corresponding unit tests.
This commit is contained in:
parent
c6526e830a
commit
eeddf1fe5d
@ -373,7 +373,6 @@
|
||||
C83509651C38706E0027C24C /* VirtualSchedulerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C835091C1C38706D0027C24C /* VirtualSchedulerTest.swift */; };
|
||||
C83509661C38706E0027C24C /* RxTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C835091D1C38706D0027C24C /* RxTest.swift */; };
|
||||
C83509671C38706E0027C24C /* Foundation+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C835091F1C38706E0027C24C /* Foundation+Extensions.swift */; };
|
||||
C83509681C38706E0027C24C /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C83509201C38706E0027C24C /* Info.plist */; };
|
||||
C83509691C38706E0027C24C /* Recorded+Timeless.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83509211C38706E0027C24C /* Recorded+Timeless.swift */; };
|
||||
C835096A1C38706E0027C24C /* TestErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83509221C38706E0027C24C /* TestErrors.swift */; };
|
||||
C835096B1C38706E0027C24C /* XCTest+AllTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83509231C38706E0027C24C /* XCTest+AllTests.swift */; };
|
||||
@ -570,6 +569,8 @@
|
||||
C8554E2D1C3051620052E67D /* PriorityQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8554E291C3051620052E67D /* PriorityQueue.swift */; };
|
||||
C85BA0591C3878850075D68E /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83508D61C38706D0027C24C /* main.swift */; };
|
||||
C85BA05A1C3878870075D68E /* PerformanceTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83508D71C38706D0027C24C /* PerformanceTools.swift */; };
|
||||
C860EC951C42E25E00A664B3 /* SectionedViewDataSourceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D132521C42DA7F00B59FFF /* SectionedViewDataSourceMock.swift */; };
|
||||
C860EC961C42E26100A664B3 /* SectionedViewDataSourceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D132521C42DA7F00B59FFF /* SectionedViewDataSourceMock.swift */; };
|
||||
C86409FC1BA593F500D3C4E8 /* Range.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86409FB1BA593F500D3C4E8 /* Range.swift */; };
|
||||
C86409FD1BA593F500D3C4E8 /* Range.swift in Sources */ = {isa = PBXBuildFile; fileRef = C86409FB1BA593F500D3C4E8 /* Range.swift */; };
|
||||
C8640A031BA5B12A00D3C4E8 /* Repeat.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8640A021BA5B12A00D3C4E8 /* Repeat.swift */; };
|
||||
@ -673,6 +674,10 @@
|
||||
C8C4B4C31C17727000828BD5 /* MessageSentObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C4B4C01C17727000828BD5 /* MessageSentObserver.swift */; };
|
||||
C8C4B4C41C17727000828BD5 /* MessageSentObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C4B4C01C17727000828BD5 /* MessageSentObserver.swift */; };
|
||||
C8C4B4C51C17727000828BD5 /* MessageSentObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C4B4C01C17727000828BD5 /* MessageSentObserver.swift */; };
|
||||
C8D132441C42D15E00B59FFF /* SectionedViewDataSourceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D132431C42D15E00B59FFF /* SectionedViewDataSourceType.swift */; };
|
||||
C8D132451C42D15E00B59FFF /* SectionedViewDataSourceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D132431C42D15E00B59FFF /* SectionedViewDataSourceType.swift */; };
|
||||
C8D132461C42D15E00B59FFF /* SectionedViewDataSourceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D132431C42D15E00B59FFF /* SectionedViewDataSourceType.swift */; };
|
||||
C8D132471C42D15E00B59FFF /* SectionedViewDataSourceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D132431C42D15E00B59FFF /* SectionedViewDataSourceType.swift */; };
|
||||
C8DB967E1BF7496C0084BD53 /* KVORepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DB967D1BF7496C0084BD53 /* KVORepresentable.swift */; };
|
||||
C8DB967F1BF7496C0084BD53 /* KVORepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DB967D1BF7496C0084BD53 /* KVORepresentable.swift */; };
|
||||
C8DB96801BF7496C0084BD53 /* KVORepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DB967D1BF7496C0084BD53 /* KVORepresentable.swift */; };
|
||||
@ -1601,6 +1606,8 @@
|
||||
C8C4B4A71C17722400828BD5 /* _RXObjCRuntime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _RXObjCRuntime.m; sourceTree = "<group>"; };
|
||||
C8C4B4A81C17722400828BD5 /* _RXObjCRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _RXObjCRuntime.h; sourceTree = "<group>"; };
|
||||
C8C4B4C01C17727000828BD5 /* MessageSentObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageSentObserver.swift; sourceTree = "<group>"; };
|
||||
C8D132431C42D15E00B59FFF /* SectionedViewDataSourceType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionedViewDataSourceType.swift; sourceTree = "<group>"; };
|
||||
C8D132521C42DA7F00B59FFF /* SectionedViewDataSourceMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionedViewDataSourceMock.swift; sourceTree = "<group>"; };
|
||||
C8DB967D1BF7496C0084BD53 /* KVORepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KVORepresentable.swift; sourceTree = "<group>"; };
|
||||
C8DB96821BF754C80084BD53 /* NSObject+Rx+KVORepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSObject+Rx+KVORepresentable.swift"; sourceTree = "<group>"; };
|
||||
C8DB96871BF756F40084BD53 /* KVORepresentable+CoreGraphics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "KVORepresentable+CoreGraphics.swift"; sourceTree = "<group>"; };
|
||||
@ -2035,6 +2042,7 @@
|
||||
C8DB96871BF756F40084BD53 /* KVORepresentable+CoreGraphics.swift */,
|
||||
C8DB968C1BF7595D0084BD53 /* KVORepresentable+Swift.swift */,
|
||||
C8BCD3F31C14B6D1005F1280 /* NSLayoutConstraint+Rx.swift */,
|
||||
C8D132431C42D15E00B59FFF /* SectionedViewDataSourceType.swift */,
|
||||
);
|
||||
path = Common;
|
||||
sourceTree = "<group>";
|
||||
@ -2149,6 +2157,7 @@
|
||||
C83508D81C38706D0027C24C /* RxCocoaTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8D132511C42DA7F00B59FFF /* TestImplementations */,
|
||||
C83508D91C38706D0027C24C /* CLLocationManager+RxTests.swift */,
|
||||
8476A01F1C3D5D580040BA22 /* UIImagePickerController+RxTests.swift */,
|
||||
C83508DA1C38706D0027C24C /* Control+RxTests+Cocoa.swift */,
|
||||
@ -2403,6 +2412,14 @@
|
||||
path = Platform;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8D132511C42DA7F00B59FFF /* TestImplementations */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C8D132521C42DA7F00B59FFF /* SectionedViewDataSourceMock.swift */,
|
||||
);
|
||||
path = TestImplementations;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C8E3A6FC1C25CE2200643FE6 /* RxTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -2960,7 +2977,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0720;
|
||||
LastUpgradeCheck = 0710;
|
||||
LastUpgradeCheck = 0720;
|
||||
ORGANIZATIONNAME = "Krunoslav Zaher";
|
||||
TargetAttributes = {
|
||||
C83508C21C386F6F0027C24C = {
|
||||
@ -3059,7 +3076,6 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C83509681C38706E0027C24C /* Info.plist in Resources */,
|
||||
C83509271C38706E0027C24C /* Info.plist in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -3198,6 +3214,7 @@
|
||||
C882542A1B8A752B00B02D69 /* UIControl+Rx.swift in Sources */,
|
||||
C8F6A1451BF0B9B1007DF367 /* NSObject+Rx+RawRepresentable.swift in Sources */,
|
||||
C8DB967E1BF7496C0084BD53 /* KVORepresentable.swift in Sources */,
|
||||
C8D132441C42D15E00B59FFF /* SectionedViewDataSourceType.swift in Sources */,
|
||||
C849EF8B1C3195950048AC4A /* Variable+Driver.swift in Sources */,
|
||||
C88254341B8A752B00B02D69 /* UITableView+Rx.swift in Sources */,
|
||||
C88254161B8A752B00B02D69 /* RxCollectionViewReactiveArrayDataSource.swift in Sources */,
|
||||
@ -3294,6 +3311,7 @@
|
||||
C8093EF81B8A732E0088E94D /* NSURLSession+Rx.swift in Sources */,
|
||||
C80DDE9C1BCE69BA006A1832 /* Driver+Operators.swift in Sources */,
|
||||
C8093F4C1B8A732E0088E94D /* NSSlider+Rx.swift in Sources */,
|
||||
C8D132451C42D15E00B59FFF /* SectionedViewDataSourceType.swift in Sources */,
|
||||
C8093EE81B8A732E0088E94D /* ControlTarget.swift in Sources */,
|
||||
C80D33901B91EF9E0014629D /* Observable+Bind.swift in Sources */,
|
||||
);
|
||||
@ -3387,6 +3405,7 @@
|
||||
C835092C1C38706E0027C24C /* Control+RxTests+UIKit.swift in Sources */,
|
||||
C83509571C38706E0027C24C /* Observable+CreationTest.swift in Sources */,
|
||||
C83509321C38706E0027C24C /* DelegateProxyTest.swift in Sources */,
|
||||
C860EC951C42E25E00A664B3 /* SectionedViewDataSourceMock.swift in Sources */,
|
||||
C83509431C38706E0027C24C /* MockDisposable.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -3457,6 +3476,7 @@
|
||||
C83509D01C38752E0027C24C /* RuntimeStateSnapshot.swift in Sources */,
|
||||
C83509AF1C3874DC0027C24C /* RxTest.swift in Sources */,
|
||||
C83509F41C38755D0027C24C /* BagTest.swift in Sources */,
|
||||
C860EC961C42E26100A664B3 /* SectionedViewDataSourceMock.swift in Sources */,
|
||||
C8350A0F1C3875630027C24C /* Observable+MultipleTest+Zip.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -4080,6 +4100,7 @@
|
||||
C8F0C0151BBBFBB9001B112F /* UIControl+Rx.swift in Sources */,
|
||||
C8F6A1481BF0B9B2007DF367 /* NSObject+Rx+RawRepresentable.swift in Sources */,
|
||||
C8DB96811BF7496C0084BD53 /* KVORepresentable.swift in Sources */,
|
||||
C8D132471C42D15E00B59FFF /* SectionedViewDataSourceType.swift in Sources */,
|
||||
C849EF8E1C3195950048AC4A /* Variable+Driver.swift in Sources */,
|
||||
C8F0C0161BBBFBB9001B112F /* UITableView+Rx.swift in Sources */,
|
||||
C8F0C0171BBBFBB9001B112F /* RxCollectionViewReactiveArrayDataSource.swift in Sources */,
|
||||
@ -4169,6 +4190,7 @@
|
||||
C8F6A1471BF0B9B2007DF367 /* NSObject+Rx+RawRepresentable.swift in Sources */,
|
||||
C8DB96801BF7496C0084BD53 /* KVORepresentable.swift in Sources */,
|
||||
C849EF8D1C3195950048AC4A /* Variable+Driver.swift in Sources */,
|
||||
C8D132461C42D15E00B59FFF /* SectionedViewDataSourceType.swift in Sources */,
|
||||
D203C4F31BB9C4CA00D02D00 /* RxCollectionViewReactiveArrayDataSource.swift in Sources */,
|
||||
D203C50B1BB9C53E00D02D00 /* UIScrollView+Rx.swift in Sources */,
|
||||
C8C4B4AB1C17722400828BD5 /* _RXObjCRuntime.m in Sources */,
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
24
RxCocoa/Common/SectionedViewDataSourceType.swift
Normal file
24
RxCocoa/Common/SectionedViewDataSourceType.swift
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// SectionedViewDataSourceType.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 1/10/16.
|
||||
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Data source with access to underlying sectioned model.
|
||||
*/
|
||||
public protocol SectionedViewDataSourceType {
|
||||
/**
|
||||
Returns model at index path.
|
||||
|
||||
In case data source doesn't contain any sections when this method is being called, `RxCocoaError.ItemsNotYetBound(object: self)` is thrown.
|
||||
|
||||
- parameter indexPath: Model index path
|
||||
- returns: Model at index path.
|
||||
*/
|
||||
func modelAtIndexPath(indexPath: NSIndexPath) throws -> Any
|
||||
}
|
@ -15,7 +15,9 @@ import RxSwift
|
||||
#endif
|
||||
|
||||
// objc monkey business
|
||||
class _RxCollectionViewReactiveArrayDataSource: NSObject, UICollectionViewDataSource {
|
||||
class _RxCollectionViewReactiveArrayDataSource
|
||||
: NSObject
|
||||
, UICollectionViewDataSource {
|
||||
|
||||
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
|
||||
return 1
|
||||
@ -38,8 +40,9 @@ class _RxCollectionViewReactiveArrayDataSource: NSObject, UICollectionViewDataSo
|
||||
}
|
||||
}
|
||||
|
||||
class RxCollectionViewReactiveArrayDataSourceSequenceWrapper<S: SequenceType> : RxCollectionViewReactiveArrayDataSource<S.Generator.Element>
|
||||
, RxCollectionViewDataSourceType {
|
||||
class RxCollectionViewReactiveArrayDataSourceSequenceWrapper<S: SequenceType>
|
||||
: RxCollectionViewReactiveArrayDataSource<S.Generator.Element>
|
||||
, RxCollectionViewDataSourceType {
|
||||
typealias Element = S
|
||||
|
||||
override init(cellFactory: CellFactory) {
|
||||
@ -61,7 +64,9 @@ class RxCollectionViewReactiveArrayDataSourceSequenceWrapper<S: SequenceType> :
|
||||
|
||||
|
||||
// Please take a look at `DelegateProxyType.swift`
|
||||
class RxCollectionViewReactiveArrayDataSource<Element> : _RxCollectionViewReactiveArrayDataSource {
|
||||
class RxCollectionViewReactiveArrayDataSource<Element>
|
||||
: _RxCollectionViewReactiveArrayDataSource
|
||||
, SectionedViewDataSourceType {
|
||||
|
||||
typealias CellFactory = (UICollectionView, Int, Element) -> UICollectionViewCell
|
||||
|
||||
@ -70,6 +75,14 @@ class RxCollectionViewReactiveArrayDataSource<Element> : _RxCollectionViewReacti
|
||||
func modelAtIndex(index: Int) -> Element? {
|
||||
return itemModels?[index]
|
||||
}
|
||||
|
||||
func modelAtIndexPath(indexPath: NSIndexPath) throws -> Any {
|
||||
precondition(indexPath.section == 0)
|
||||
guard let item = itemModels?[indexPath.item] else {
|
||||
throw RxCocoaError.ItemsNotYetBound(object: self)
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
var cellFactory: CellFactory
|
||||
|
||||
|
@ -15,7 +15,9 @@ import RxSwift
|
||||
#endif
|
||||
|
||||
// objc monkey business
|
||||
class _RxTableViewReactiveArrayDataSource: NSObject, UITableViewDataSource {
|
||||
class _RxTableViewReactiveArrayDataSource
|
||||
: NSObject
|
||||
, UITableViewDataSource {
|
||||
|
||||
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
|
||||
return 1
|
||||
@ -39,14 +41,15 @@ class _RxTableViewReactiveArrayDataSource: NSObject, UITableViewDataSource {
|
||||
}
|
||||
|
||||
|
||||
class RxTableViewReactiveArrayDataSourceSequenceWrapper<S: SequenceType> : RxTableViewReactiveArrayDataSource<S.Generator.Element>
|
||||
, RxTableViewDataSourceType {
|
||||
class RxTableViewReactiveArrayDataSourceSequenceWrapper<S: SequenceType>
|
||||
: RxTableViewReactiveArrayDataSource<S.Generator.Element>
|
||||
, RxTableViewDataSourceType {
|
||||
typealias Element = S
|
||||
|
||||
override init(cellFactory: CellFactory) {
|
||||
super.init(cellFactory: cellFactory)
|
||||
}
|
||||
|
||||
|
||||
func tableView(tableView: UITableView, observedEvent: Event<S>) {
|
||||
switch observedEvent {
|
||||
case .Next(let value):
|
||||
@ -60,7 +63,9 @@ class RxTableViewReactiveArrayDataSourceSequenceWrapper<S: SequenceType> : RxTab
|
||||
}
|
||||
|
||||
// Please take a look at `DelegateProxyType.swift`
|
||||
class RxTableViewReactiveArrayDataSource<Element> : _RxTableViewReactiveArrayDataSource {
|
||||
class RxTableViewReactiveArrayDataSource<Element>
|
||||
: _RxTableViewReactiveArrayDataSource
|
||||
, SectionedViewDataSourceType {
|
||||
typealias CellFactory = (UITableView, Int, Element) -> UITableViewCell
|
||||
|
||||
var itemModels: [Element]? = nil
|
||||
@ -68,7 +73,15 @@ class RxTableViewReactiveArrayDataSource<Element> : _RxTableViewReactiveArrayDat
|
||||
func modelAtIndex(index: Int) -> Element? {
|
||||
return itemModels?[index]
|
||||
}
|
||||
|
||||
|
||||
func modelAtIndexPath(indexPath: NSIndexPath) throws -> Any {
|
||||
precondition(indexPath.section == 0)
|
||||
guard let item = itemModels?[indexPath.item] else {
|
||||
throw RxCocoaError.ItemsNotYetBound(object: self)
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
let cellFactory: CellFactory
|
||||
|
||||
init(cellFactory: CellFactory) {
|
||||
|
@ -133,27 +133,29 @@ extension UICollectionView {
|
||||
|
||||
return ControlEvent(events: source)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` message `collectionView:didSelectItemAtIndexPath:`.
|
||||
*/
|
||||
public var rx_itemDeselected: ControlEvent<NSIndexPath> {
|
||||
let source = rx_delegate.observe("collectionView:didDeselectItemAtIndexPath:")
|
||||
.map { a in
|
||||
return a[1] as! NSIndexPath
|
||||
}
|
||||
|
||||
return ControlEvent(events: source)
|
||||
}
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` message `collectionView:didSelectItemAtIndexPath:`.
|
||||
|
||||
It can be only used when one of the `rx_itemsWith*` methods is used to bind observable sequence,
|
||||
or any other data source conforming to `SectionedViewDataSourceType` protocol.
|
||||
|
||||
It can be only used when one of the `rx_itemsWith*` methods is used to bind observable sequence.
|
||||
|
||||
```
|
||||
collectionView.rx_modelSelected(MyModel.self)
|
||||
.map { ...
|
||||
|
||||
If custom data source is being bound, new `rx_modelSelected` wrapper needs to be written also.
|
||||
|
||||
public func rx_myModelSelected<T>() -> ControlEvent<T> {
|
||||
let source: Observable<T> = rx_itemSelected.map { indexPath in
|
||||
let dataSource: MyDataSource = self.rx_dataSource.forwardToDelegate() as! MyDataSource
|
||||
|
||||
return dataSource.modelAtIndex(indexPath.item)!
|
||||
}
|
||||
|
||||
return ControlEvent(source: source)
|
||||
}
|
||||
|
||||
```
|
||||
*/
|
||||
public func rx_modelSelected<T>(modelType: T.Type) -> ControlEvent<T> {
|
||||
let source: Observable<T> = rx_itemSelected.flatMap { [weak self] indexPath -> Observable<T> in
|
||||
@ -166,18 +168,39 @@ extension UICollectionView {
|
||||
|
||||
return ControlEvent(events: source)
|
||||
}
|
||||
|
||||
/**
|
||||
Reactive wrapper for `delegate` message `collectionView:didSelectItemAtIndexPath:`.
|
||||
|
||||
It can be only used when one of the `rx_itemsWith*` methods is used to bind observable sequence,
|
||||
or any other data source conforming to `SectionedViewDataSourceType` protocol.
|
||||
|
||||
```
|
||||
collectionView.rx_modelDeselected(MyModel.self)
|
||||
.map { ...
|
||||
```
|
||||
*/
|
||||
public func rx_modelDeselected<T>(modelType: T.Type) -> ControlEvent<T> {
|
||||
let source: Observable<T> = rx_itemDeselected.flatMap { [weak self] indexPath -> Observable<T> in
|
||||
guard let view = self else {
|
||||
return Observable.empty()
|
||||
}
|
||||
|
||||
return Observable.just(try view.rx_modelAtIndexPath(indexPath))
|
||||
}
|
||||
|
||||
return ControlEvent(events: source)
|
||||
}
|
||||
|
||||
/**
|
||||
Syncronous helper method for retrieving a model at indexPath through a reactive data source
|
||||
*/
|
||||
public func rx_modelAtIndexPath<T>(indexPath: NSIndexPath) throws -> T {
|
||||
let dataSource: RxCollectionViewReactiveArrayDataSource<T> = castOrFatalError(self.rx_dataSource.forwardToDelegate(), message: "This method only works in case one of the `rx_itemsWith*` methods was used.")
|
||||
let dataSource: SectionedViewDataSourceType = castOrFatalError(self.rx_dataSource.forwardToDelegate(), message: "This method only works in case one of the `rx_itemsWith*` methods was used.")
|
||||
|
||||
guard let element = dataSource.modelAtIndex(indexPath.item) else {
|
||||
throw RxCocoaError.ItemsNotYetBound(object: self)
|
||||
}
|
||||
|
||||
return element
|
||||
let element = try dataSource.modelAtIndexPath(indexPath)
|
||||
|
||||
return element as! T
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -193,22 +193,13 @@ extension UITableView {
|
||||
/**
|
||||
Reactive wrapper for `delegate` message `tableView:didSelectRowAtIndexPath:`.
|
||||
|
||||
It can be only used when one of the `rx_itemsWith*` methods is used to bind observable sequence.
|
||||
It can be only used when one of the `rx_itemsWith*` methods is used to bind observable sequence,
|
||||
or any other data source conforming to `SectionedViewDataSourceType` protocol.
|
||||
|
||||
```
|
||||
tableView.rx_modelSelected(MyModel.self)
|
||||
.map { ...
|
||||
|
||||
If custom data source is being bound, new `rx_modelSelected` wrapper needs to be written also.
|
||||
|
||||
public func rx_myModelSelected<T>() -> ControlEvent<T> {
|
||||
let source: Observable<T> = rx_itemSelected.map { indexPath in
|
||||
let dataSource: MyDataSource = self.rx_dataSource.forwardToDelegate() as! MyDataSource
|
||||
|
||||
return dataSource.modelAtIndex(indexPath.item)!
|
||||
}
|
||||
|
||||
return ControlEvent(source: source)
|
||||
}
|
||||
```
|
||||
*/
|
||||
public func rx_modelSelected<T>(modelType: T.Type) -> ControlEvent<T> {
|
||||
let source: Observable<T> = rx_itemSelected.flatMap { [weak self] indexPath -> Observable<T> in
|
||||
@ -225,22 +216,13 @@ extension UITableView {
|
||||
/**
|
||||
Reactive wrapper for `delegate` message `tableView:didDeselectRowAtIndexPath:`.
|
||||
|
||||
It can be only used when one of the `rx_itemsWith*` methods is used to bind observable sequence.
|
||||
It can be only used when one of the `rx_itemsWith*` methods is used to bind observable sequence,
|
||||
or any other data source conforming to `SectionedViewDataSourceType` protocol.
|
||||
|
||||
tableView.rx_modelSelected(MyModel.self)
|
||||
.map { ...
|
||||
|
||||
If custom data source is being bound, new `rx_modelSelected` wrapper needs to be written also.
|
||||
|
||||
public func rx_myModelDeselected<T>() -> ControlEvent<T> {
|
||||
let source: Observable<T> = rx_itemDeselected.map { indexPath in
|
||||
let dataSource: MyDataSource = self.rx_dataSource.forwardToDelegate() as! MyDataSource
|
||||
|
||||
return dataSource.modelAtIndex(indexPath.item)!
|
||||
}
|
||||
|
||||
return ControlEvent(source: source)
|
||||
}
|
||||
```
|
||||
tableView.rx_modelDeselected(MyModel.self)
|
||||
.map { ...
|
||||
```
|
||||
*/
|
||||
public func rx_modelDeselected<T>(modelType: T.Type) -> ControlEvent<T> {
|
||||
let source: Observable<T> = rx_itemDeselected.flatMap { [weak self] indexPath -> Observable<T> in
|
||||
@ -255,16 +237,14 @@ extension UITableView {
|
||||
}
|
||||
|
||||
/**
|
||||
Synchronous helper method for retrieving a model at indexPath through a reactive data source
|
||||
Synchronous helper method for retrieving a model at indexPath through a reactive data source.
|
||||
*/
|
||||
public func rx_modelAtIndexPath<T>(indexPath: NSIndexPath) throws -> T {
|
||||
let dataSource: RxTableViewReactiveArrayDataSource<T> = castOrFatalError(self.rx_dataSource.forwardToDelegate(), message: "This method only works in case one of the `rx_items*` methods was used.")
|
||||
let dataSource: SectionedViewDataSourceType = castOrFatalError(self.rx_dataSource.forwardToDelegate(), message: "This method only works in case one of the `rx_items*` methods was used.")
|
||||
|
||||
guard let element = dataSource.modelAtIndex(indexPath.item) else {
|
||||
throw RxCocoaError.ItemsNotYetBound(object: self)
|
||||
}
|
||||
|
||||
return element
|
||||
let element = try dataSource.modelAtIndexPath(indexPath)
|
||||
|
||||
return element as! T
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0710"
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -106,7 +106,7 @@ extension ControlTests {
|
||||
ensureEventDeallocated(createView) { (view: UICollectionView) in view.rx_modelSelected(Int.self) }
|
||||
}
|
||||
|
||||
func testCollectionView_ModelSelected1() {
|
||||
func testCollectionView_ModelSelected_itemsWithCellFactory() {
|
||||
let items: Observable<[Int]> = Observable.just([1, 2, 3])
|
||||
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
@ -137,7 +137,7 @@ extension ControlTests {
|
||||
s.dispose()
|
||||
}
|
||||
|
||||
func testCollectionView_ModelSelected2() {
|
||||
func testCollectionView_ModelSelected_itemsWithCellIdentifier() {
|
||||
let items: Observable<[Int]> = Observable.just([1, 2, 3])
|
||||
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
@ -167,6 +167,90 @@ extension ControlTests {
|
||||
s.dispose()
|
||||
dataSourceSubscription.dispose()
|
||||
}
|
||||
|
||||
func testCollectionView_ModelDeselected_itemsWithCellFactory() {
|
||||
let items: Observable<[Int]> = Observable.just([1, 2, 3])
|
||||
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
|
||||
let createView: () -> (UICollectionView, Disposable) = {
|
||||
let collectionView = UICollectionView(frame: CGRectMake(0, 0, 1, 1), collectionViewLayout: layout)
|
||||
let s = items.bindTo(collectionView.rx_itemsWithCellFactory) { (cv, index: Int, item: Int) -> UICollectionViewCell in
|
||||
return UICollectionViewCell(frame: CGRectMake(1, 1, 1, 1))
|
||||
}
|
||||
|
||||
return (collectionView, s)
|
||||
}
|
||||
|
||||
let (collectionView, dataSourceSubscription) = createView()
|
||||
|
||||
var selectedItem: Int? = nil
|
||||
|
||||
let s = collectionView.rx_modelDeselected(Int.self)
|
||||
.subscribeNext { (item: Int) in
|
||||
selectedItem = item
|
||||
}
|
||||
|
||||
collectionView.delegate!.collectionView!(collectionView, didDeselectItemAtIndexPath: NSIndexPath(forRow: 1, inSection: 0))
|
||||
|
||||
XCTAssertEqual(selectedItem, 2)
|
||||
|
||||
dataSourceSubscription.dispose()
|
||||
s.dispose()
|
||||
}
|
||||
|
||||
func testCollectionView_ModelDeselected_itemsWithCellIdentifier() {
|
||||
let items: Observable<[Int]> = Observable.just([1, 2, 3])
|
||||
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
let createView: () -> (UICollectionView, Disposable) = {
|
||||
let collectionView = UICollectionView(frame: CGRectMake(0, 0, 1, 1), collectionViewLayout: layout)
|
||||
collectionView.registerClass(NSClassFromString("UICollectionViewCell"), forCellWithReuseIdentifier: "a")
|
||||
let dataSourceSubscription = items.bindTo(collectionView.rx_itemsWithCellIdentifier("a")) { (index: Int, item: Int, cell) in
|
||||
|
||||
}
|
||||
|
||||
return (collectionView, dataSourceSubscription)
|
||||
|
||||
}
|
||||
let (collectionView, dataSourceSubscription) = createView()
|
||||
|
||||
var selectedItem: Int? = nil
|
||||
|
||||
let s = collectionView.rx_modelDeselected(Int.self)
|
||||
.subscribeNext { item in
|
||||
selectedItem = item
|
||||
}
|
||||
|
||||
collectionView.delegate!.collectionView!(collectionView, didDeselectItemAtIndexPath: NSIndexPath(forRow: 1, inSection: 0))
|
||||
|
||||
XCTAssertEqual(selectedItem, 2)
|
||||
|
||||
s.dispose()
|
||||
dataSourceSubscription.dispose()
|
||||
}
|
||||
|
||||
func testCollectionView_modelAtIndexPath_normal() {
|
||||
let items: Observable<[Int]> = Observable.just([1, 2, 3])
|
||||
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
let createView: () -> (UICollectionView, Disposable) = {
|
||||
let collectionView = UICollectionView(frame: CGRectMake(0, 0, 1, 1), collectionViewLayout: layout)
|
||||
collectionView.registerClass(NSClassFromString("UICollectionViewCell"), forCellWithReuseIdentifier: "a")
|
||||
let dataSource = SectionedViewDataSourceMock()
|
||||
let dataSourceSubscription = items.bindTo(collectionView.rx_itemsWithDataSource(dataSource))
|
||||
|
||||
return (collectionView, dataSourceSubscription)
|
||||
|
||||
}
|
||||
let (collectionView, dataSourceSubscription) = createView()
|
||||
|
||||
let model: Int = try! collectionView.rx_modelAtIndexPath(NSIndexPath(forItem: 1, inSection: 0))
|
||||
|
||||
XCTAssertEqual(model, 2)
|
||||
|
||||
dataSourceSubscription.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
// UILabel
|
||||
@ -246,7 +330,7 @@ extension ControlTests {
|
||||
ensureEventDeallocated(createView) { (view: UITableView) in view.rx_modelSelected(Int.self) }
|
||||
}
|
||||
|
||||
func testTableView_ModelSelected1() {
|
||||
func testTableView_ModelSelected_rx_itemsWithCellFactory() {
|
||||
let items: Observable<[Int]> = Observable.just([1, 2, 3])
|
||||
|
||||
let createView: () -> (UITableView, Disposable) = {
|
||||
@ -275,7 +359,7 @@ extension ControlTests {
|
||||
s.dispose()
|
||||
}
|
||||
|
||||
func testTableView_ModelSelected2() {
|
||||
func testTableView_ModelSelected_itemsWithCellIdentifier() {
|
||||
let items: Observable<[Int]> = Observable.just([1, 2, 3])
|
||||
|
||||
let createView: () -> (UITableView, Disposable) = {
|
||||
@ -304,6 +388,86 @@ extension ControlTests {
|
||||
dataSourceSubscription.dispose()
|
||||
s.dispose()
|
||||
}
|
||||
|
||||
func testTableView_ModelDeselected_rx_itemsWithCellFactory() {
|
||||
let items: Observable<[Int]> = Observable.just([1, 2, 3])
|
||||
|
||||
let createView: () -> (UITableView, Disposable) = {
|
||||
let tableView = UITableView(frame: CGRectMake(0, 0, 1, 1))
|
||||
let dataSourceSubscription = items.bindTo(tableView.rx_itemsWithCellFactory) { (tv, index: Int, item: Int) -> UITableViewCell in
|
||||
return UITableViewCell(style: .Default, reuseIdentifier: "Identity")
|
||||
}
|
||||
|
||||
return (tableView, dataSourceSubscription)
|
||||
}
|
||||
|
||||
let (tableView, dataSourceSubscription) = createView()
|
||||
|
||||
var selectedItem: Int? = nil
|
||||
|
||||
let s = tableView.rx_modelDeselected(Int.self)
|
||||
.subscribeNext { item in
|
||||
selectedItem = item
|
||||
}
|
||||
|
||||
tableView.delegate!.tableView!(tableView, didDeselectRowAtIndexPath: NSIndexPath(forRow: 1, inSection: 0))
|
||||
|
||||
XCTAssertEqual(selectedItem, 2)
|
||||
|
||||
dataSourceSubscription.dispose()
|
||||
s.dispose()
|
||||
}
|
||||
|
||||
func testTableView_ModelDeselected_itemsWithCellIdentifier() {
|
||||
let items: Observable<[Int]> = Observable.just([1, 2, 3])
|
||||
|
||||
let createView: () -> (UITableView, Disposable) = {
|
||||
let tableView = UITableView(frame: CGRectMake(0, 0, 1, 1))
|
||||
tableView.registerClass(NSClassFromString("UITableViewCell"), forCellReuseIdentifier: "a")
|
||||
let dataSourceSubscription = items.bindTo(tableView.rx_itemsWithCellIdentifier("a")) { (index: Int, item: Int, cell) in
|
||||
|
||||
}
|
||||
|
||||
return (tableView, dataSourceSubscription)
|
||||
}
|
||||
|
||||
let (tableView, dataSourceSubscription) = createView()
|
||||
|
||||
var selectedItem: Int? = nil
|
||||
|
||||
let s = tableView.rx_modelDeselected(Int.self)
|
||||
.subscribeNext { item in
|
||||
selectedItem = item
|
||||
}
|
||||
|
||||
tableView.delegate!.tableView!(tableView, didDeselectRowAtIndexPath: NSIndexPath(forRow: 1, inSection: 0))
|
||||
|
||||
XCTAssertEqual(selectedItem, 2)
|
||||
|
||||
dataSourceSubscription.dispose()
|
||||
s.dispose()
|
||||
}
|
||||
|
||||
func testTableView_modelAtIndexPath_normal() {
|
||||
let items: Observable<[Int]> = Observable.just([1, 2, 3])
|
||||
|
||||
let createView: () -> (UITableView, Disposable) = {
|
||||
let tableView = UITableView(frame: CGRectMake(0, 0, 1, 1))
|
||||
tableView.registerClass(NSClassFromString("UITableViewCell"), forCellReuseIdentifier: "a")
|
||||
let dataSource = SectionedViewDataSourceMock()
|
||||
let dataSourceSubscription = items.bindTo(tableView.rx_itemsWithDataSource(dataSource))
|
||||
|
||||
return (tableView, dataSourceSubscription)
|
||||
}
|
||||
|
||||
let (tableView, dataSourceSubscription) = createView()
|
||||
|
||||
let model: Int = try! tableView.rx_modelAtIndexPath(NSIndexPath(forItem: 1, inSection: 0))
|
||||
|
||||
XCTAssertEqual(model, 2)
|
||||
|
||||
dataSourceSubscription.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
// UIControl
|
||||
|
@ -0,0 +1,57 @@
|
||||
//
|
||||
// SectionedViewDataSourceMock.swift
|
||||
// Rx
|
||||
//
|
||||
// Created by Krunoslav Zaher on 1/10/16.
|
||||
// Copyright © 2016 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import UIKit
|
||||
|
||||
@objc class SectionedViewDataSourceMock
|
||||
: NSObject
|
||||
, SectionedViewDataSourceType
|
||||
, UITableViewDataSource
|
||||
, UICollectionViewDataSource
|
||||
, RxTableViewDataSourceType
|
||||
, RxCollectionViewDataSourceType {
|
||||
|
||||
typealias Element = [Int]
|
||||
|
||||
var items: [Int]?
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
func modelAtIndexPath(indexPath: NSIndexPath) throws -> Any {
|
||||
return items![indexPath.item]
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
|
||||
return UITableViewCell()
|
||||
}
|
||||
|
||||
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
|
||||
return UICollectionViewCell()
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, observedEvent: Event<Element>) {
|
||||
items = observedEvent.element!
|
||||
}
|
||||
|
||||
func collectionView(collectionView: UICollectionView, observedEvent: Event<Element>) {
|
||||
items = observedEvent.element!
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user