├── .gitignore
├── .swift-version
├── .swiftlint.yml
├── Cartfile
├── Cartfile.private
├── Cartfile.resolved
├── LICENSE
├── Package.swift
├── README.md
├── Resources
├── Info.plist
└── RxResponderChain.h
├── RxResponderChain.podspec
├── RxResponderChain.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ └── xcschemes
│ └── RxResponderChain.xcscheme
├── Sources
└── ResponderChain+Rx.swift
└── Tests
├── LinuxMain.swift
└── RxResponderChainTests
└── RxResponderChainTests.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xcuserstate
23 |
24 | ## Obj-C/Swift specific
25 | *.hmap
26 | *.ipa
27 | *.dSYM.zip
28 | *.dSYM
29 |
30 | ## Playgrounds
31 | timeline.xctimeline
32 | playground.xcworkspace
33 |
34 | # Swift Package Manager
35 | #
36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37 | Packages/
38 | .build/
39 |
40 | # CocoaPods
41 | #
42 | # We recommend against adding the Pods directory to your .gitignore. However
43 | # you should judge for yourself, the pros and cons are mentioned at:
44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45 | #
46 | # Pods/
47 |
48 | # Carthage
49 | #
50 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
51 | Carthage/Checkouts
52 |
53 | Carthage/Build
54 |
55 | # fastlane
56 | #
57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
58 | # screenshots whenever they are needed.
59 | # For more information about the recommended setup visit:
60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
61 |
62 | fastlane/report.xml
63 | fastlane/Preview.html
64 | fastlane/screenshots
65 | fastlane/test_output
66 |
67 | # macOS
68 | .DS_Store
69 |
--------------------------------------------------------------------------------
/.swift-version:
--------------------------------------------------------------------------------
1 | 4.1.0
2 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | included:
2 | - Sources/
3 |
4 | line_length: 130
5 | file_length: 500
6 |
--------------------------------------------------------------------------------
/Cartfile:
--------------------------------------------------------------------------------
1 | github "ReactiveX/RxSwift" ~> 4.1
2 |
--------------------------------------------------------------------------------
/Cartfile.private:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ukitaka/RxResponderChain/3af17a0a376e0dcc3e32d5d6e191bc08cb57d8a0/Cartfile.private
--------------------------------------------------------------------------------
/Cartfile.resolved:
--------------------------------------------------------------------------------
1 | github "ReactiveX/RxSwift" "4.1.2"
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 ukitaka
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | import PackageDescription
2 |
3 | let package = Package(
4 | name: "RxResponderChain",
5 | dependencies: [
6 | .Package(url: "git@github.com:ReactiveX/RxSwift.git", majorVersion: 3)
7 | ]
8 | )
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RxResponderChain
2 | `RxResponderChain` is an extension of `RxSwift`, `RxCocoa`.
3 | It provides the way to notify Rx events via responder chain.
4 |
5 | ## Usage
6 | First, you have to create struct / class / enum represents event you want to notify using `ResponderChainEvent` protocol.
7 |
8 | ```swift
9 | import RxResponder
10 |
11 | struct LikeTweetEvent: ResponderChainEvent {
12 | let tweetID: Int64
13 | }
14 | ```
15 |
16 | Generate event object and pass it to `bindTo` (or, `on`, `onNext` … ).
17 |
18 | ```swift
19 | final class TweetCell: UITableViewCell {
20 | ...
21 |
22 | override func awakeFromNib() {
23 | super.awakeFromNib()
24 |
25 | likeButton.rx.tap
26 | .map { _ in LikeTweetEvent(tweetID: self.tweet.id) }
27 | .bind(to: self.rx.responderChain)
28 | .disposed(by: disposeBag)
29 | }
30 | }
31 | ```
32 |
33 | Then you can receive events in classes that are on responder chain of the class sends events.
34 | For example, if you send event in `UITableViewCell` then you can receive them in `tableView`, `viewController.view`, `viewController`, `viewController.navigationController`, and so on.
35 |
36 | ```swift
37 | final class TweetListViewController: UIViewController {
38 | ...
39 |
40 | override func viewDidLoad() {
41 | super.viewDidLoad()
42 |
43 | self.rx.responderChain.event(LikeTweetEvent.self)
44 | .flatMapFirst { e in twitterService.like(tweetID: e.tweetID) }
45 | .subscribe()
46 | .disposed(by:disposeBag)
47 | }
48 | }
49 | ```
50 |
51 | ## Requirements
52 |
53 | `RxResponderChain` requires / supports the following environments:
54 |
55 | + Swift 4.1 / Xcode 9.3
56 | + iOS 9.0 or later
57 | + RxSwift / RxCocoa ~> 4.1
58 |
59 | ## Installation
60 |
61 | ### Carthage
62 |
63 | ```ruby
64 | github "ukitaka/RxResponderChain" ~> 2.0
65 | ```
66 |
67 |
68 | ### CocoaPods
69 |
70 | ```ruby
71 | use_frameworks!
72 | pod "RxResponderChain", "~> 2.0"
73 | ```
74 |
75 |
--------------------------------------------------------------------------------
/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 2.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Resources/RxResponderChain.h:
--------------------------------------------------------------------------------
1 | //
2 | // RxResponderChain.h
3 | // RxResponderChain
4 | //
5 | // Created by ST20841 on 2017/02/22.
6 | // Copyright © 2017年 waft. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for RxResponderChain.
12 | FOUNDATION_EXPORT double RxResponderChainVersionNumber;
13 |
14 | //! Project version string for RxResponderChain.
15 | FOUNDATION_EXPORT const unsigned char RxResponderChainVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/RxResponderChain.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "RxResponderChain"
3 | s.version = "2.0.0"
4 | s.summary = "Notify Rx events via responder chain"
5 | s.description = <<-DESC
6 | `RxResponderChain` is an extension of `RxSwift`, `RxCocoa`.
7 | It provides the way to notify Rx events via responder chain.
8 | DESC
9 |
10 | s.homepage = "https://github.com/ukitaka/RxResponderChain"
11 | s.license = { :type => "MIT", :file => "LICENSE" }
12 | s.author = { "ukitaka" => "yuki.takahashi.1126@gmail.com" }
13 |
14 | s.platform = :ios, "9.0"
15 | s.source = { :git => "https://github.com/ukitaka/RxResponderChain.git", :tag => "#{s.version}" }
16 | s.source_files = "Sources/*.swift"
17 |
18 | s.requires_arc = true
19 |
20 | s.dependency "RxSwift", "~> 4.1"
21 | s.dependency "RxCocoa", "~> 4.1"
22 | end
23 |
24 |
--------------------------------------------------------------------------------
/RxResponderChain.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 261463CC1E5D89B700699242 /* RxResponderChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 261463CA1E5D89B700699242 /* RxResponderChain.h */; settings = {ATTRIBUTES = (Public, ); }; };
11 | 261463D71E5D8A1500699242 /* RxResponderChain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 261463BE1E5D884A00699242 /* RxResponderChain.framework */; };
12 | 261463E01E5D8A5F00699242 /* RxResponderChainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261463DE1E5D8A5000699242 /* RxResponderChainTests.swift */; };
13 | 261463E21E5D8AFF00699242 /* ResponderChain+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261463E11E5D8AFF00699242 /* ResponderChain+Rx.swift */; };
14 | 261463E61E5D8B7200699242 /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 261463E41E5D8B7200699242 /* RxCocoa.framework */; };
15 | 261463E71E5D8B7200699242 /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 261463E51E5D8B7200699242 /* RxSwift.framework */; };
16 | E807502C1E5E597E00005DDB /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 261463E41E5D8B7200699242 /* RxCocoa.framework */; };
17 | E807502D1E5E597E00005DDB /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 261463E51E5D8B7200699242 /* RxSwift.framework */; };
18 | E80750301E5E597E00005DDB /* RxBlocking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E807502E1E5E597E00005DDB /* RxBlocking.framework */; };
19 | E80750311E5E597E00005DDB /* RxTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E807502F1E5E597E00005DDB /* RxTest.framework */; };
20 | E8F330A31E5E607A00898A5F /* RxBlocking.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = E807502E1E5E597E00005DDB /* RxBlocking.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
21 | E8F330A41E5E607A00898A5F /* RxTest.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = E807502F1E5E597E00005DDB /* RxTest.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
22 | E8F330A51E5E607A00898A5F /* RxCocoa.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 261463E41E5D8B7200699242 /* RxCocoa.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
23 | E8F330A61E5E607A00898A5F /* RxSwift.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 261463E51E5D8B7200699242 /* RxSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
24 | /* End PBXBuildFile section */
25 |
26 | /* Begin PBXContainerItemProxy section */
27 | 261463D81E5D8A1500699242 /* PBXContainerItemProxy */ = {
28 | isa = PBXContainerItemProxy;
29 | containerPortal = 261463B51E5D884A00699242 /* Project object */;
30 | proxyType = 1;
31 | remoteGlobalIDString = 261463BD1E5D884A00699242;
32 | remoteInfo = RxResponderChain;
33 | };
34 | /* End PBXContainerItemProxy section */
35 |
36 | /* Begin PBXCopyFilesBuildPhase section */
37 | E8F330A21E5E606D00898A5F /* CopyFiles */ = {
38 | isa = PBXCopyFilesBuildPhase;
39 | buildActionMask = 2147483647;
40 | dstPath = "";
41 | dstSubfolderSpec = 10;
42 | files = (
43 | E8F330A31E5E607A00898A5F /* RxBlocking.framework in CopyFiles */,
44 | E8F330A41E5E607A00898A5F /* RxTest.framework in CopyFiles */,
45 | E8F330A51E5E607A00898A5F /* RxCocoa.framework in CopyFiles */,
46 | E8F330A61E5E607A00898A5F /* RxSwift.framework in CopyFiles */,
47 | );
48 | runOnlyForDeploymentPostprocessing = 0;
49 | };
50 | /* End PBXCopyFilesBuildPhase section */
51 |
52 | /* Begin PBXFileReference section */
53 | 261463BE1E5D884A00699242 /* RxResponderChain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RxResponderChain.framework; sourceTree = BUILT_PRODUCTS_DIR; };
54 | 261463C91E5D89B700699242 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Resources/Info.plist; sourceTree = SOURCE_ROOT; };
55 | 261463CA1E5D89B700699242 /* RxResponderChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RxResponderChain.h; path = Resources/RxResponderChain.h; sourceTree = SOURCE_ROOT; };
56 | 261463D21E5D8A1500699242 /* RxResponderChainTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RxResponderChainTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
57 | 261463DE1E5D8A5000699242 /* RxResponderChainTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxResponderChainTests.swift; sourceTree = ""; };
58 | 261463E11E5D8AFF00699242 /* ResponderChain+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ResponderChain+Rx.swift"; sourceTree = ""; };
59 | 261463E41E5D8B7200699242 /* RxCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxCocoa.framework; path = Carthage/Build/iOS/RxCocoa.framework; sourceTree = ""; };
60 | 261463E51E5D8B7200699242 /* RxSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxSwift.framework; path = Carthage/Build/iOS/RxSwift.framework; sourceTree = ""; };
61 | E807502E1E5E597E00005DDB /* RxBlocking.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxBlocking.framework; path = Carthage/Build/iOS/RxBlocking.framework; sourceTree = ""; };
62 | E807502F1E5E597E00005DDB /* RxTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxTest.framework; path = Carthage/Build/iOS/RxTest.framework; sourceTree = ""; };
63 | /* End PBXFileReference section */
64 |
65 | /* Begin PBXFrameworksBuildPhase section */
66 | 261463BA1E5D884A00699242 /* Frameworks */ = {
67 | isa = PBXFrameworksBuildPhase;
68 | buildActionMask = 2147483647;
69 | files = (
70 | 261463E61E5D8B7200699242 /* RxCocoa.framework in Frameworks */,
71 | 261463E71E5D8B7200699242 /* RxSwift.framework in Frameworks */,
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | 261463CF1E5D8A1500699242 /* Frameworks */ = {
76 | isa = PBXFrameworksBuildPhase;
77 | buildActionMask = 2147483647;
78 | files = (
79 | E80750301E5E597E00005DDB /* RxBlocking.framework in Frameworks */,
80 | E80750311E5E597E00005DDB /* RxTest.framework in Frameworks */,
81 | E807502C1E5E597E00005DDB /* RxCocoa.framework in Frameworks */,
82 | E807502D1E5E597E00005DDB /* RxSwift.framework in Frameworks */,
83 | 261463D71E5D8A1500699242 /* RxResponderChain.framework in Frameworks */,
84 | );
85 | runOnlyForDeploymentPostprocessing = 0;
86 | };
87 | /* End PBXFrameworksBuildPhase section */
88 |
89 | /* Begin PBXGroup section */
90 | 261463B41E5D884A00699242 = {
91 | isa = PBXGroup;
92 | children = (
93 | 261463CD1E5D89D800699242 /* Sources */,
94 | 261463C01E5D884A00699242 /* Resources */,
95 | 261463D31E5D8A1500699242 /* Tests */,
96 | 261463BF1E5D884A00699242 /* Products */,
97 | 261463E31E5D8B7100699242 /* Frameworks */,
98 | );
99 | sourceTree = "";
100 | };
101 | 261463BF1E5D884A00699242 /* Products */ = {
102 | isa = PBXGroup;
103 | children = (
104 | 261463BE1E5D884A00699242 /* RxResponderChain.framework */,
105 | 261463D21E5D8A1500699242 /* RxResponderChainTests.xctest */,
106 | );
107 | name = Products;
108 | sourceTree = "";
109 | };
110 | 261463C01E5D884A00699242 /* Resources */ = {
111 | isa = PBXGroup;
112 | children = (
113 | 261463C91E5D89B700699242 /* Info.plist */,
114 | 261463CA1E5D89B700699242 /* RxResponderChain.h */,
115 | );
116 | name = Resources;
117 | path = RxResponderChain;
118 | sourceTree = "";
119 | };
120 | 261463CD1E5D89D800699242 /* Sources */ = {
121 | isa = PBXGroup;
122 | children = (
123 | 261463E11E5D8AFF00699242 /* ResponderChain+Rx.swift */,
124 | );
125 | path = Sources;
126 | sourceTree = "";
127 | };
128 | 261463D31E5D8A1500699242 /* Tests */ = {
129 | isa = PBXGroup;
130 | children = (
131 | 261463DD1E5D8A3D00699242 /* RxResponderChainTests */,
132 | );
133 | path = Tests;
134 | sourceTree = "";
135 | };
136 | 261463DD1E5D8A3D00699242 /* RxResponderChainTests */ = {
137 | isa = PBXGroup;
138 | children = (
139 | 261463DE1E5D8A5000699242 /* RxResponderChainTests.swift */,
140 | );
141 | path = RxResponderChainTests;
142 | sourceTree = "";
143 | };
144 | 261463E31E5D8B7100699242 /* Frameworks */ = {
145 | isa = PBXGroup;
146 | children = (
147 | E807502E1E5E597E00005DDB /* RxBlocking.framework */,
148 | E807502F1E5E597E00005DDB /* RxTest.framework */,
149 | 261463E41E5D8B7200699242 /* RxCocoa.framework */,
150 | 261463E51E5D8B7200699242 /* RxSwift.framework */,
151 | );
152 | name = Frameworks;
153 | sourceTree = "";
154 | };
155 | /* End PBXGroup section */
156 |
157 | /* Begin PBXHeadersBuildPhase section */
158 | 261463BB1E5D884A00699242 /* Headers */ = {
159 | isa = PBXHeadersBuildPhase;
160 | buildActionMask = 2147483647;
161 | files = (
162 | 261463CC1E5D89B700699242 /* RxResponderChain.h in Headers */,
163 | );
164 | runOnlyForDeploymentPostprocessing = 0;
165 | };
166 | /* End PBXHeadersBuildPhase section */
167 |
168 | /* Begin PBXNativeTarget section */
169 | 261463BD1E5D884A00699242 /* RxResponderChain */ = {
170 | isa = PBXNativeTarget;
171 | buildConfigurationList = 261463C61E5D884A00699242 /* Build configuration list for PBXNativeTarget "RxResponderChain" */;
172 | buildPhases = (
173 | 261463B91E5D884A00699242 /* Sources */,
174 | 261463BA1E5D884A00699242 /* Frameworks */,
175 | 261463BB1E5D884A00699242 /* Headers */,
176 | 261463BC1E5D884A00699242 /* Resources */,
177 | 26D537001E5E794400F4FC4E /* SwiftLint */,
178 | );
179 | buildRules = (
180 | );
181 | dependencies = (
182 | );
183 | name = RxResponderChain;
184 | productName = RxResponderChain;
185 | productReference = 261463BE1E5D884A00699242 /* RxResponderChain.framework */;
186 | productType = "com.apple.product-type.framework";
187 | };
188 | 261463D11E5D8A1500699242 /* RxResponderChainTests */ = {
189 | isa = PBXNativeTarget;
190 | buildConfigurationList = 261463DA1E5D8A1500699242 /* Build configuration list for PBXNativeTarget "RxResponderChainTests" */;
191 | buildPhases = (
192 | 261463CE1E5D8A1500699242 /* Sources */,
193 | 261463CF1E5D8A1500699242 /* Frameworks */,
194 | 261463D01E5D8A1500699242 /* Resources */,
195 | E8F330A21E5E606D00898A5F /* CopyFiles */,
196 | );
197 | buildRules = (
198 | );
199 | dependencies = (
200 | 261463D91E5D8A1500699242 /* PBXTargetDependency */,
201 | );
202 | name = RxResponderChainTests;
203 | productName = RxResponderChainTests;
204 | productReference = 261463D21E5D8A1500699242 /* RxResponderChainTests.xctest */;
205 | productType = "com.apple.product-type.bundle.unit-test";
206 | };
207 | /* End PBXNativeTarget section */
208 |
209 | /* Begin PBXProject section */
210 | 261463B51E5D884A00699242 /* Project object */ = {
211 | isa = PBXProject;
212 | attributes = {
213 | LastSwiftUpdateCheck = 0820;
214 | LastUpgradeCheck = 0930;
215 | ORGANIZATIONNAME = waft;
216 | TargetAttributes = {
217 | 261463BD1E5D884A00699242 = {
218 | CreatedOnToolsVersion = 8.2.1;
219 | DevelopmentTeam = G73SPYZ3Q7;
220 | LastSwiftMigration = 0930;
221 | ProvisioningStyle = Automatic;
222 | };
223 | 261463D11E5D8A1500699242 = {
224 | CreatedOnToolsVersion = 8.2.1;
225 | DevelopmentTeam = G73SPYZ3Q7;
226 | LastSwiftMigration = 0930;
227 | ProvisioningStyle = Automatic;
228 | };
229 | };
230 | };
231 | buildConfigurationList = 261463B81E5D884A00699242 /* Build configuration list for PBXProject "RxResponderChain" */;
232 | compatibilityVersion = "Xcode 3.2";
233 | developmentRegion = English;
234 | hasScannedForEncodings = 0;
235 | knownRegions = (
236 | en,
237 | );
238 | mainGroup = 261463B41E5D884A00699242;
239 | productRefGroup = 261463BF1E5D884A00699242 /* Products */;
240 | projectDirPath = "";
241 | projectRoot = "";
242 | targets = (
243 | 261463BD1E5D884A00699242 /* RxResponderChain */,
244 | 261463D11E5D8A1500699242 /* RxResponderChainTests */,
245 | );
246 | };
247 | /* End PBXProject section */
248 |
249 | /* Begin PBXResourcesBuildPhase section */
250 | 261463BC1E5D884A00699242 /* Resources */ = {
251 | isa = PBXResourcesBuildPhase;
252 | buildActionMask = 2147483647;
253 | files = (
254 | );
255 | runOnlyForDeploymentPostprocessing = 0;
256 | };
257 | 261463D01E5D8A1500699242 /* Resources */ = {
258 | isa = PBXResourcesBuildPhase;
259 | buildActionMask = 2147483647;
260 | files = (
261 | );
262 | runOnlyForDeploymentPostprocessing = 0;
263 | };
264 | /* End PBXResourcesBuildPhase section */
265 |
266 | /* Begin PBXShellScriptBuildPhase section */
267 | 26D537001E5E794400F4FC4E /* SwiftLint */ = {
268 | isa = PBXShellScriptBuildPhase;
269 | buildActionMask = 2147483647;
270 | files = (
271 | );
272 | inputPaths = (
273 | );
274 | name = SwiftLint;
275 | outputPaths = (
276 | );
277 | runOnlyForDeploymentPostprocessing = 0;
278 | shellPath = /bin/sh;
279 | shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
280 | };
281 | /* End PBXShellScriptBuildPhase section */
282 |
283 | /* Begin PBXSourcesBuildPhase section */
284 | 261463B91E5D884A00699242 /* Sources */ = {
285 | isa = PBXSourcesBuildPhase;
286 | buildActionMask = 2147483647;
287 | files = (
288 | 261463E21E5D8AFF00699242 /* ResponderChain+Rx.swift in Sources */,
289 | );
290 | runOnlyForDeploymentPostprocessing = 0;
291 | };
292 | 261463CE1E5D8A1500699242 /* Sources */ = {
293 | isa = PBXSourcesBuildPhase;
294 | buildActionMask = 2147483647;
295 | files = (
296 | 261463E01E5D8A5F00699242 /* RxResponderChainTests.swift in Sources */,
297 | );
298 | runOnlyForDeploymentPostprocessing = 0;
299 | };
300 | /* End PBXSourcesBuildPhase section */
301 |
302 | /* Begin PBXTargetDependency section */
303 | 261463D91E5D8A1500699242 /* PBXTargetDependency */ = {
304 | isa = PBXTargetDependency;
305 | target = 261463BD1E5D884A00699242 /* RxResponderChain */;
306 | targetProxy = 261463D81E5D8A1500699242 /* PBXContainerItemProxy */;
307 | };
308 | /* End PBXTargetDependency section */
309 |
310 | /* Begin XCBuildConfiguration section */
311 | 261463C41E5D884A00699242 /* Debug */ = {
312 | isa = XCBuildConfiguration;
313 | buildSettings = {
314 | ALWAYS_SEARCH_USER_PATHS = NO;
315 | CLANG_ANALYZER_NONNULL = YES;
316 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
317 | CLANG_CXX_LIBRARY = "libc++";
318 | CLANG_ENABLE_MODULES = YES;
319 | CLANG_ENABLE_OBJC_ARC = YES;
320 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
321 | CLANG_WARN_BOOL_CONVERSION = YES;
322 | CLANG_WARN_COMMA = YES;
323 | CLANG_WARN_CONSTANT_CONVERSION = YES;
324 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
325 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
326 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
327 | CLANG_WARN_EMPTY_BODY = YES;
328 | CLANG_WARN_ENUM_CONVERSION = YES;
329 | CLANG_WARN_INFINITE_RECURSION = YES;
330 | CLANG_WARN_INT_CONVERSION = YES;
331 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
332 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
333 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
334 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
335 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
336 | CLANG_WARN_STRICT_PROTOTYPES = YES;
337 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
338 | CLANG_WARN_UNREACHABLE_CODE = YES;
339 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
340 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
341 | COPY_PHASE_STRIP = NO;
342 | CURRENT_PROJECT_VERSION = 1;
343 | DEBUG_INFORMATION_FORMAT = dwarf;
344 | ENABLE_STRICT_OBJC_MSGSEND = YES;
345 | ENABLE_TESTABILITY = YES;
346 | GCC_C_LANGUAGE_STANDARD = gnu99;
347 | GCC_DYNAMIC_NO_PIC = NO;
348 | GCC_NO_COMMON_BLOCKS = YES;
349 | GCC_OPTIMIZATION_LEVEL = 0;
350 | GCC_PREPROCESSOR_DEFINITIONS = (
351 | "DEBUG=1",
352 | "$(inherited)",
353 | );
354 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
355 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
356 | GCC_WARN_UNDECLARED_SELECTOR = YES;
357 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
358 | GCC_WARN_UNUSED_FUNCTION = YES;
359 | GCC_WARN_UNUSED_VARIABLE = YES;
360 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
361 | MTL_ENABLE_DEBUG_INFO = YES;
362 | ONLY_ACTIVE_ARCH = YES;
363 | SDKROOT = iphoneos;
364 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
365 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
366 | SWIFT_VERSION = "";
367 | TARGETED_DEVICE_FAMILY = "1,2";
368 | VERSIONING_SYSTEM = "apple-generic";
369 | VERSION_INFO_PREFIX = "";
370 | };
371 | name = Debug;
372 | };
373 | 261463C51E5D884A00699242 /* Release */ = {
374 | isa = XCBuildConfiguration;
375 | buildSettings = {
376 | ALWAYS_SEARCH_USER_PATHS = NO;
377 | CLANG_ANALYZER_NONNULL = YES;
378 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
379 | CLANG_CXX_LIBRARY = "libc++";
380 | CLANG_ENABLE_MODULES = YES;
381 | CLANG_ENABLE_OBJC_ARC = YES;
382 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
383 | CLANG_WARN_BOOL_CONVERSION = YES;
384 | CLANG_WARN_COMMA = YES;
385 | CLANG_WARN_CONSTANT_CONVERSION = YES;
386 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
387 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
388 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
389 | CLANG_WARN_EMPTY_BODY = YES;
390 | CLANG_WARN_ENUM_CONVERSION = YES;
391 | CLANG_WARN_INFINITE_RECURSION = YES;
392 | CLANG_WARN_INT_CONVERSION = YES;
393 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
394 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
395 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
396 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
397 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
398 | CLANG_WARN_STRICT_PROTOTYPES = YES;
399 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
400 | CLANG_WARN_UNREACHABLE_CODE = YES;
401 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
402 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
403 | COPY_PHASE_STRIP = NO;
404 | CURRENT_PROJECT_VERSION = 1;
405 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
406 | ENABLE_NS_ASSERTIONS = NO;
407 | ENABLE_STRICT_OBJC_MSGSEND = YES;
408 | GCC_C_LANGUAGE_STANDARD = gnu99;
409 | GCC_NO_COMMON_BLOCKS = YES;
410 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
411 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
412 | GCC_WARN_UNDECLARED_SELECTOR = YES;
413 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
414 | GCC_WARN_UNUSED_FUNCTION = YES;
415 | GCC_WARN_UNUSED_VARIABLE = YES;
416 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
417 | MTL_ENABLE_DEBUG_INFO = NO;
418 | SDKROOT = iphoneos;
419 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
420 | SWIFT_VERSION = "";
421 | TARGETED_DEVICE_FAMILY = "1,2";
422 | VALIDATE_PRODUCT = YES;
423 | VERSIONING_SYSTEM = "apple-generic";
424 | VERSION_INFO_PREFIX = "";
425 | };
426 | name = Release;
427 | };
428 | 261463C71E5D884A00699242 /* Debug */ = {
429 | isa = XCBuildConfiguration;
430 | buildSettings = {
431 | CLANG_ENABLE_MODULES = YES;
432 | CODE_SIGN_IDENTITY = "";
433 | DEFINES_MODULE = YES;
434 | DEVELOPMENT_TEAM = G73SPYZ3Q7;
435 | DYLIB_COMPATIBILITY_VERSION = 1;
436 | DYLIB_CURRENT_VERSION = 1;
437 | DYLIB_INSTALL_NAME_BASE = "@rpath";
438 | FRAMEWORK_SEARCH_PATHS = (
439 | "$(inherited)",
440 | "$(PROJECT_DIR)/Carthage/Build/iOS",
441 | );
442 | INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist";
443 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
444 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
445 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
446 | PRODUCT_BUNDLE_IDENTIFIER = me.waft.RxResponderChain;
447 | PRODUCT_NAME = "$(TARGET_NAME)";
448 | SKIP_INSTALL = YES;
449 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
450 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
451 | SWIFT_VERSION = 4.0;
452 | };
453 | name = Debug;
454 | };
455 | 261463C81E5D884A00699242 /* Release */ = {
456 | isa = XCBuildConfiguration;
457 | buildSettings = {
458 | CLANG_ENABLE_MODULES = YES;
459 | CODE_SIGN_IDENTITY = "";
460 | DEFINES_MODULE = YES;
461 | DEVELOPMENT_TEAM = G73SPYZ3Q7;
462 | DYLIB_COMPATIBILITY_VERSION = 1;
463 | DYLIB_CURRENT_VERSION = 1;
464 | DYLIB_INSTALL_NAME_BASE = "@rpath";
465 | FRAMEWORK_SEARCH_PATHS = (
466 | "$(inherited)",
467 | "$(PROJECT_DIR)/Carthage/Build/iOS",
468 | );
469 | INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist";
470 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
471 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
472 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
473 | PRODUCT_BUNDLE_IDENTIFIER = me.waft.RxResponderChain;
474 | PRODUCT_NAME = "$(TARGET_NAME)";
475 | SKIP_INSTALL = YES;
476 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
477 | SWIFT_VERSION = 4.0;
478 | };
479 | name = Release;
480 | };
481 | 261463DB1E5D8A1500699242 /* Debug */ = {
482 | isa = XCBuildConfiguration;
483 | buildSettings = {
484 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
485 | DEVELOPMENT_TEAM = G73SPYZ3Q7;
486 | FRAMEWORK_SEARCH_PATHS = (
487 | "$(inherited)",
488 | "$(PROJECT_DIR)/Carthage/Build/iOS",
489 | );
490 | INFOPLIST_FILE = Resources/Info.plist;
491 | IPHONEOS_DEPLOYMENT_TARGET = 10.2;
492 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
493 | PRODUCT_BUNDLE_IDENTIFIER = me.waft.RxResponderChainTests;
494 | PRODUCT_NAME = "$(TARGET_NAME)";
495 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
496 | SWIFT_VERSION = 4.0;
497 | };
498 | name = Debug;
499 | };
500 | 261463DC1E5D8A1500699242 /* Release */ = {
501 | isa = XCBuildConfiguration;
502 | buildSettings = {
503 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
504 | DEVELOPMENT_TEAM = G73SPYZ3Q7;
505 | FRAMEWORK_SEARCH_PATHS = (
506 | "$(inherited)",
507 | "$(PROJECT_DIR)/Carthage/Build/iOS",
508 | );
509 | INFOPLIST_FILE = Resources/Info.plist;
510 | IPHONEOS_DEPLOYMENT_TARGET = 10.2;
511 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
512 | PRODUCT_BUNDLE_IDENTIFIER = me.waft.RxResponderChainTests;
513 | PRODUCT_NAME = "$(TARGET_NAME)";
514 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
515 | SWIFT_VERSION = 4.0;
516 | };
517 | name = Release;
518 | };
519 | /* End XCBuildConfiguration section */
520 |
521 | /* Begin XCConfigurationList section */
522 | 261463B81E5D884A00699242 /* Build configuration list for PBXProject "RxResponderChain" */ = {
523 | isa = XCConfigurationList;
524 | buildConfigurations = (
525 | 261463C41E5D884A00699242 /* Debug */,
526 | 261463C51E5D884A00699242 /* Release */,
527 | );
528 | defaultConfigurationIsVisible = 0;
529 | defaultConfigurationName = Release;
530 | };
531 | 261463C61E5D884A00699242 /* Build configuration list for PBXNativeTarget "RxResponderChain" */ = {
532 | isa = XCConfigurationList;
533 | buildConfigurations = (
534 | 261463C71E5D884A00699242 /* Debug */,
535 | 261463C81E5D884A00699242 /* Release */,
536 | );
537 | defaultConfigurationIsVisible = 0;
538 | defaultConfigurationName = Release;
539 | };
540 | 261463DA1E5D8A1500699242 /* Build configuration list for PBXNativeTarget "RxResponderChainTests" */ = {
541 | isa = XCConfigurationList;
542 | buildConfigurations = (
543 | 261463DB1E5D8A1500699242 /* Debug */,
544 | 261463DC1E5D8A1500699242 /* Release */,
545 | );
546 | defaultConfigurationIsVisible = 0;
547 | defaultConfigurationName = Release;
548 | };
549 | /* End XCConfigurationList section */
550 | };
551 | rootObject = 261463B51E5D884A00699242 /* Project object */;
552 | }
553 |
--------------------------------------------------------------------------------
/RxResponderChain.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/RxResponderChain.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/RxResponderChain.xcodeproj/xcshareddata/xcschemes/RxResponderChain.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
65 |
71 |
72 |
73 |
74 |
75 |
76 |
82 |
83 |
89 |
90 |
91 |
92 |
94 |
95 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/Sources/ResponderChain+Rx.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIResponder+Rx.swift
3 | // RxResponderChain
4 | //
5 | // Created by Yuki Takahashi on 2017/02/22.
6 | // Copyright © 2017年 waft. All rights reserved.
7 | //
8 |
9 | #if os(iOS)
10 |
11 | import RxSwift
12 | import RxCocoa
13 |
14 | // MARK: - ResponderChainEvent
15 |
16 | public protocol ResponderChainEvent {
17 | }
18 |
19 | // MARK: - ResponderChain
20 |
21 | public struct ResponderChain: ObserverType {
22 | fileprivate let reactive: Reactive
23 |
24 | fileprivate init(_ reactive: Reactive) {
25 | self.reactive = reactive
26 | }
27 |
28 | public func on(_ event: RxSwift.Event) {
29 | var currentResponder: UIResponder? = reactive.base
30 | while let responder = currentResponder {
31 | responder.rx.responderChainEventObserver.on(event)
32 | currentResponder = responder.next
33 | }
34 | }
35 |
36 | public func event(_ type: E.Type) -> Observable {
37 | return reactive.responderChainEventObserver
38 | .filter {
39 | $0 is E
40 | }
41 | .map {
42 | castOrFatalError($0) as E
43 | }
44 | }
45 | }
46 |
47 | // MARK: - Reactive
48 |
49 | private var responderChainEventObserverContext: UInt8 = 0
50 |
51 | public extension Reactive where Base: UIResponder {
52 | public var responderChain: ResponderChain {
53 | return ResponderChain(self)
54 | }
55 |
56 | fileprivate var responderChainEventObserver: PublishSubject {
57 | if let observer = objc_getAssociatedObject(base, &responderChainEventObserverContext)
58 | as? PublishSubject {
59 | return observer
60 | }
61 |
62 | let observer = PublishSubject()
63 |
64 | objc_setAssociatedObject(base, &responderChainEventObserverContext, observer, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
65 | return observer
66 | }
67 | }
68 |
69 | // MARK: - Bind
70 |
71 | public extension ObservableType where E: ResponderChainEvent {
72 |
73 | @available(*, deprecated, renamed: "bind(to:)")
74 | public func bindTo(_ observer: O) -> Disposable where O: ObserverType, O.E == Self.E {
75 | return bind(to: observer)
76 | }
77 |
78 | public func bind(to observer: O) -> Disposable where O.E == ResponderChainEvent {
79 | return self.map { $0 as ResponderChainEvent }
80 | .bind(to: observer)
81 | }
82 | }
83 |
84 | // MARK: - Utils
85 |
86 | private func castOrFatalError(_ value: Any!) -> T {
87 | let maybeResult: T? = value as? T
88 | guard let result = maybeResult else {
89 | fatalError("Failure converting from \(value) to \(T.self)")
90 | }
91 | return result
92 | }
93 |
94 | #endif
95 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import RxResponderChainTests
3 |
4 | XCTMain([
5 | testCase(RxResponderChainTests.allTests),
6 | ])
7 |
--------------------------------------------------------------------------------
/Tests/RxResponderChainTests/RxResponderChainTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | #if os(iOS)
4 | import UIKit
5 | import RxSwift
6 | import RxCocoa
7 | import RxTest
8 | #endif
9 |
10 | @testable import RxResponderChain
11 |
12 | class RxResponderChainTests: XCTestCase {
13 | static var allTests : [(String, (RxResponderChainTests) -> () throws -> Void)] {
14 | return [
15 | ]
16 | }
17 |
18 | #if os(iOS)
19 | struct TestEvent: ResponderChainEvent, Equatable {
20 | let a: Int
21 |
22 | static func == (lhs: TestEvent, rhs: TestEvent) -> Bool {
23 | return lhs.a == rhs.a
24 | }
25 | }
26 |
27 | struct TestEvent2: ResponderChainEvent, Equatable {
28 | let a: Int
29 |
30 | static func == (lhs: TestEvent2, rhs: TestEvent2) -> Bool {
31 | return lhs.a == rhs.a
32 | }
33 | }
34 |
35 | let disposeBag = DisposeBag()
36 |
37 | func testResponderChainEvent() {
38 | let viewController = UIViewController()
39 | let view = viewController.view!
40 | let subview1 = UIView()
41 | let subview2 = UIView()
42 | view.addSubview(subview1)
43 | view.addSubview(subview2)
44 |
45 |
46 | let scheduler = TestScheduler(initialClock: 0)
47 |
48 | let xs = scheduler.createHotObservable([
49 | next(100, TestEvent(a: 1)),
50 | next(200, TestEvent(a: 2)),
51 | next(300, TestEvent(a: 3)),
52 | next(400, TestEvent(a: 4)),
53 | ])
54 |
55 | let observerForView = scheduler.createObserver(TestEvent.self)
56 | let observerForVC = scheduler.createObserver(TestEvent.self)
57 |
58 | let observerForSubview = scheduler.createObserver(TestEvent.self)
59 | let observerForTestEvent2 = scheduler.createObserver(TestEvent2.self)
60 |
61 | scheduler.scheduleAt(0) {
62 | view.rx.responderChain.event(TestEvent.self)
63 | .subscribe(observerForView)
64 | .disposed(by: self.disposeBag)
65 |
66 | viewController.rx.responderChain.event(TestEvent.self)
67 | .subscribe(observerForVC)
68 | .disposed(by:self.disposeBag)
69 |
70 | subview2.rx.responderChain.event(TestEvent.self)
71 | .subscribe(observerForSubview)
72 | .disposed(by:self.disposeBag)
73 |
74 | view.rx.responderChain.event(TestEvent2.self)
75 | .subscribe(observerForTestEvent2)
76 | .disposed(by:self.disposeBag)
77 |
78 | xs.bind(to:viewController.view.rx.responderChain)
79 | .disposed(by:self.disposeBag)
80 | }
81 |
82 | scheduler.start()
83 |
84 | let expectedEvent = [
85 | next(100, TestEvent(a: 1)),
86 | next(200, TestEvent(a: 2)),
87 | next(300, TestEvent(a: 3)),
88 | next(400, TestEvent(a: 4)),
89 | ]
90 |
91 | XCTAssertEqual(observerForView.events, expectedEvent)
92 | XCTAssertEqual(observerForVC.events, expectedEvent)
93 | XCTAssertEqual(observerForSubview.events, [])
94 | XCTAssertEqual(observerForTestEvent2.events, [])
95 |
96 | }
97 | #endif
98 | }
99 |
--------------------------------------------------------------------------------