├── .gitignore
├── .gitmodules
├── Cartfile
├── Cartfile.resolved
├── Example
├── .swiftlint.yml
├── Podfile
├── Podfile.lock
├── RxGesture-OSX
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Base.lproj
│ │ └── Main.storyboard
│ ├── Info.plist
│ └── ViewController.swift
├── RxGesture.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── RxGesture_iOS_Demo.xcscheme
├── RxGesture.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── RxGesture
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ ├── LaunchScreen.xib
│ └── Main.storyboard
│ ├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Info.plist
│ └── ViewController.swift
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── Package.swift
├── Pod
├── Assets
│ ├── .gitkeep
│ └── demo.gif
└── Classes
│ ├── .gitkeep
│ ├── GenericRxGestureRecognizerDelegate.swift
│ ├── GestureFactory.swift
│ ├── GestureRecognizer+RxGesture.swift
│ ├── OSX
│ ├── NSClickGestureRecognizer+RxGesture.swift
│ ├── NSGestureRecognizer+Rx.swift
│ ├── NSMagnificationGestureRecognizer+RxGesture.swift
│ ├── NSPanGestureRecognizer+RxGesture.swift
│ ├── NSPressGestureRecognizer+RxGesture.swift
│ └── NSRotationGestureRecognizer+RxGesture.swift
│ ├── SharedTypes.swift
│ ├── View+RxGesture.swift
│ └── iOS
│ ├── ForceTouchGestureRecognizer.swift
│ ├── TouchDownGestureRecognizer.swift
│ ├── TransformGestureRecognizers.swift
│ ├── UIHoverGestureRecognizer+RxGesture.swift
│ ├── UILongPressGestureRecognizer+RxGesture.swift
│ ├── UIPanGestureRecognizer+RxGesture.swift
│ ├── UIPinchGestureRecognizer+RxGesture.swift
│ ├── UIRotationGestureRecognizer+RxGesture.swift
│ ├── UIScreenEdgePanGestureRecognizer+RxGesture.swift
│ ├── UISwipeGestureRecognizer+RxGesture.swift
│ └── UITapGestureRecognizer+RxGesture.swift
├── README.md
├── RxGesture.podspec
├── RxGesture
├── .swiftlint.yml
├── RxGesture copy-Info.plist
├── RxGesture-iOS-Tests
│ ├── Info.plist
│ └── RxGestureTests.swift
├── RxGesture.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── RxGesture-OSX.xcscheme
│ │ └── RxGesture-iOS.xcscheme
└── RxGesture
│ ├── Info.plist
│ └── RxGesture.h
└── bin
└── setup
/.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 | ## SPM Generated
10 | *.xcodeproj
11 | *.resolved
12 | .swiftpm/
13 |
14 | ## Various settings
15 | *.pbxuser
16 | !default.pbxuser
17 | *.mode1v3
18 | !default.mode1v3
19 | *.mode2v3
20 | !default.mode2v3
21 | *.perspectivev3
22 | !default.perspectivev3
23 | xcuserdata
24 |
25 | ## Other
26 | *.xccheckout
27 | *.moved-aside
28 | *.xcuserstate
29 | *.xcscmblueprint
30 |
31 | ## Obj-C/Swift specific
32 | *.hmap
33 | *.ipa
34 |
35 | ## Playgrounds
36 | timeline.xctimeline
37 | playground.xcworkspace
38 |
39 | # Swift Package Manager
40 | #
41 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
42 | # Packages/
43 | .build/
44 |
45 | # CocoaPods
46 | #
47 | # We recommend against adding the Pods directory to your .gitignore. However
48 | # you should judge for yourself, the pros and cons are mentioned at:
49 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
50 | #
51 | # Pods/
52 | !Example/*.xcodeproj
53 |
54 | # Carthage
55 | #
56 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
57 | # Carthage/Checkouts
58 |
59 | Carthage/Build
60 |
61 | # fastlane
62 | #
63 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
64 | # screenshots whenever they are needed.
65 | # For more information about the recommended setup visit:
66 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
67 |
68 | fastlane/report.xml
69 | fastlane/screenshots
70 | Example/Pods
71 |
72 | .DS_Store
73 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Carthage/Checkouts/RxSwift"]
2 | path = Carthage/Checkouts/RxSwift
3 | url = https://github.com/ReactiveX/RxSwift.git
4 |
--------------------------------------------------------------------------------
/Cartfile:
--------------------------------------------------------------------------------
1 | github "ReactiveX/RxSwift" ~> 6.0
--------------------------------------------------------------------------------
/Cartfile.resolved:
--------------------------------------------------------------------------------
1 | github "ReactiveX/RxSwift" "6.1.0"
2 |
--------------------------------------------------------------------------------
/Example/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | excluded:
2 | - Pods
3 |
4 | opt_in_rules:
5 | - overridden_super_call
6 | - private_outlet
7 | - prohibited_super_call
8 | - first_where
9 | - closure_spacing
10 | - unneeded_parentheses_in_closure_argument
11 | - redundant_nil_coalescing
12 | - pattern_matching_keywords
13 | - explicit_init
14 | - contains_over_first_not_nil
15 | - implicit_return
16 |
17 | disabled_rules:
18 | - line_length
19 | - trailing_whitespace
20 | - type_name
21 | - identifier_name
22 | - vertical_whitespace
23 | - trailing_newline
24 | - opening_brace
25 | - large_tuple
26 | - file_length
27 | - comma
28 | - colon
29 | - private_over_fileprivate
30 | - force_cast
31 | - force_try
32 | - function_parameter_count
33 | - statement_position
34 | - legacy_hashing
35 | - todo
36 | - operator_whitespace
37 | - type_body_length
38 | - function_body_length
39 | - cyclomatic_complexity
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://cdn.cocoapods.org/'
2 | use_frameworks!
3 |
4 | def commonDependencies
5 | pod 'RxGesture', :path => '../'
6 | pod 'RxSwift', '~> 6.0'
7 | pod 'RxCocoa', '~> 6.0'
8 | end
9 |
10 | target 'RxGesture_iOS_Demo' do
11 | platform :ios, '9.0'
12 | commonDependencies
13 | end
14 |
15 | target 'RxGesture_OSX_Demo' do
16 | platform :osx, '10.10'
17 | commonDependencies
18 | end
19 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - RxCocoa (6.0.0):
3 | - RxRelay (= 6.0.0)
4 | - RxSwift (= 6.0.0)
5 | - RxGesture (4.0.0):
6 | - RxCocoa (~> 6.0)
7 | - RxSwift (~> 6.0)
8 | - RxRelay (6.0.0):
9 | - RxSwift (= 6.0.0)
10 | - RxSwift (6.0.0)
11 |
12 | DEPENDENCIES:
13 | - RxCocoa (~> 6.0)
14 | - RxGesture (from `../`)
15 | - RxSwift (~> 6.0)
16 |
17 | SPEC REPOS:
18 | trunk:
19 | - RxCocoa
20 | - RxRelay
21 | - RxSwift
22 |
23 | EXTERNAL SOURCES:
24 | RxGesture:
25 | :path: "../"
26 |
27 | SPEC CHECKSUMS:
28 | RxCocoa: 3f79328fafa3645b34600f37c31e64c73ae3a80e
29 | RxGesture: b095a86df33d199a33b46a644e7c58bdef8ab035
30 | RxRelay: 8d593be109c06ea850df027351beba614b012ffb
31 | RxSwift: c14e798c59b9f6e9a2df8fd235602e85cc044295
32 |
33 | PODFILE CHECKSUM: d48d39de6335e342c666df2ee12e4efb3d005eb3
34 |
35 | COCOAPODS: 1.10.1
36 |
--------------------------------------------------------------------------------
/Example/RxGesture-OSX/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // RxGesture-OSX
4 | //
5 | // Created by Marin Todorov on 3/24/16.
6 | // Copyright © 2016 CocoaPods. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | @NSApplicationMain
12 | class AppDelegate: NSObject, NSApplicationDelegate {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/Example/RxGesture-OSX/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "size" : "16x16",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "size" : "16x16",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "size" : "32x32",
16 | "scale" : "1x"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "size" : "32x32",
21 | "scale" : "2x"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "size" : "128x128",
26 | "scale" : "1x"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "size" : "128x128",
31 | "scale" : "2x"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "size" : "256x256",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "size" : "256x256",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "size" : "512x512",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "size" : "512x512",
51 | "scale" : "2x"
52 | }
53 | ],
54 | "info" : {
55 | "version" : 1,
56 | "author" : "xcode"
57 | }
58 | }
--------------------------------------------------------------------------------
/Example/RxGesture-OSX/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSMinimumSystemVersion
26 | $(MACOSX_DEPLOYMENT_TARGET)
27 | NSHumanReadableCopyright
28 | Copyright © 2016 CocoaPods. All rights reserved.
29 | NSMainStoryboardFile
30 | Main
31 | NSPrincipalClass
32 | NSApplication
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Example/RxGesture-OSX/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // RxGesture-OSX
4 | //
5 | // Created by Marin Todorov on 3/24/16.
6 | // Copyright © 2016 CocoaPods. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | import RxSwift
12 | import RxCocoa
13 | import RxGesture
14 |
15 | class Step {
16 | enum Action { case previous, next }
17 |
18 | let title: String
19 | let code: String
20 | let install: (NSView, NSTextField, @escaping () -> Void, DisposeBag) -> Void
21 |
22 | init(title: String, code: String, install: @escaping (NSView, NSTextField, @escaping () -> Void, DisposeBag) -> Void) {
23 | self.title = title
24 | self.code = code
25 | self.install = install
26 | }
27 | }
28 |
29 | class MacViewController: NSViewController {
30 |
31 | @IBOutlet private weak var myView: NSView!
32 | @IBOutlet private weak var myViewText: NSTextField!
33 | @IBOutlet private weak var info: NSTextField!
34 | @IBOutlet private var code: NSTextView!
35 |
36 | fileprivate let nextStepObserver = PublishSubject()
37 | fileprivate let bag = DisposeBag()
38 | fileprivate var stepBag = DisposeBag()
39 |
40 | override func viewWillAppear() {
41 | super.viewWillAppear()
42 |
43 | view.wantsLayer = true
44 |
45 | myView.wantsLayer = true
46 | myView.layer?.backgroundColor = NSColor.red.cgColor
47 | myView.layer?.cornerRadius = 5
48 |
49 | let steps: [Step] = [
50 | clickStep,
51 | doubleClickStep,
52 | rightClickStep,
53 | anyClickStep,
54 | pressStep,
55 | panStep,
56 | rotateStep,
57 | magnificationStep
58 | ]
59 |
60 | func newIndex(for index: Int, action: Step.Action) -> Int {
61 | switch action {
62 | case .previous:
63 | return (steps.count + index - 1) % steps.count
64 | case .next:
65 | return (steps.count + index + 1) % steps.count
66 | }
67 | }
68 |
69 | nextStepObserver
70 | .scan(0, accumulator: newIndex)
71 | .startWith(0)
72 | .map { (steps[$0], $0) }
73 | .subscribe(onNext: { [unowned self] in self.updateStep($0, at: $1) })
74 | .disposed(by: bag)
75 | }
76 |
77 | override func viewDidAppear() {
78 | super.viewDidAppear()
79 | updateAnchorPoint()
80 | }
81 |
82 | private func updateAnchorPoint() {
83 | let frame = myView.layer!.frame
84 | myView.layer!.anchorPoint = CGPoint(x: 0.5, y: 0.5)
85 | myView.layer!.frame = frame
86 | }
87 |
88 | @IBAction func previousStep(_ sender: Any) {
89 | nextStepObserver.onNext(.previous)
90 | }
91 |
92 | @IBAction func nextStep(_ sender: Any) {
93 | nextStepObserver.onNext(.next)
94 | }
95 |
96 | func updateStep(_ step: Step, at index: Int) {
97 | stepBag = DisposeBag()
98 |
99 | info.stringValue = "\(index + 1). " + step.title
100 | code.string = step.code
101 |
102 | myViewText.stringValue = ""
103 | step.install(myView, myViewText, { [nextStepObserver] in nextStepObserver.onNext(.next) }, stepBag)
104 |
105 | print("active gestures: \(myView.gestureRecognizers.count)")
106 | }
107 |
108 | lazy var clickStep: Step = Step(
109 | title: "Click the square",
110 | code: """
111 | view.rx
112 | .leftClickGesture()
113 | .when(.recognized)
114 | .subscribe(onNext: { _ in
115 | // Do something
116 | })
117 | .disposed(by: disposeBag)
118 | """,
119 | install: { view, _, nextStep, stepBag in
120 |
121 | view.animateTransform(to: CATransform3DIdentity)
122 | view.animateBackgroundColor(to: .red)
123 |
124 | view.rx
125 | .leftClickGesture()
126 | .when(.recognized)
127 | .subscribe(onNext: { _ in
128 | nextStep()
129 | })
130 | .disposed(by: stepBag)
131 | })
132 |
133 | lazy var doubleClickStep: Step = Step(
134 | title: "Double click the square",
135 | code: """
136 | view.rx
137 | .leftClickGesture { gesture, _ in
138 | gesture.numberOfClicksRequired = 2
139 | }
140 | .when(.recognized)
141 | .subscribe(onNext: { _ in
142 | // Do something
143 | })
144 | .disposed(by: disposeBag)
145 | """,
146 | install: { view, _, nextStep, stepBag in
147 |
148 | view.animateTransform(to: CATransform3DIdentity)
149 | view.animateBackgroundColor(to: .green)
150 |
151 | view.rx
152 | .leftClickGesture { gesture, _ in
153 | gesture.numberOfClicksRequired = 2
154 | }
155 | .when(.recognized)
156 | .subscribe(onNext: { _ in
157 | nextStep()
158 | })
159 | .disposed(by: stepBag)
160 | })
161 |
162 | lazy var rightClickStep: Step = Step(
163 | title: "Right click the square",
164 | code: """
165 | view.rx
166 | .rightClickGesture()
167 | .when(.recognized)
168 | .subscribe(onNext: { _ in
169 | // Do something
170 | })
171 | .disposed(by: disposeBag)
172 | """,
173 | install: { view, _, nextStep, stepBag in
174 |
175 | view.animateTransform(to: CATransform3DIdentity)
176 | view.animateBackgroundColor(to: .blue)
177 |
178 | view.rx
179 | .rightClickGesture()
180 | .when(.recognized)
181 | .subscribe(onNext: { _ in
182 | nextStep()
183 | })
184 | .disposed(by: stepBag)
185 | })
186 |
187 | lazy var anyClickStep: Step = Step(
188 | title: "Click any button (left or right)",
189 | code: """
190 | view.rx
191 | .anyGesture(.leftClick(), .rightClick())
192 | .when(.recognized)
193 | .subscribe(onNext: { _ in
194 | // Do something
195 | })
196 | .disposed(by: disposeBag)
197 | """,
198 | install: { view, _, nextStep, stepBag in
199 |
200 | view.animateTransform(to: CATransform3DMakeScale(1.5, 1.5, 1.0))
201 | view.animateBackgroundColor(to: .red)
202 |
203 | view.rx
204 | .anyGesture(.leftClick(), .rightClick())
205 | .when(.recognized)
206 | .subscribe(onNext: { _ in
207 | nextStep()
208 | })
209 | .disposed(by: stepBag)
210 | })
211 |
212 | lazy var pressStep: Step = Step(
213 | title: "Long press the square",
214 | code: """
215 | view.rx
216 | .pressGesture()
217 | .when(.began)
218 | .subscribe(onNext: { _ in
219 | // Do something
220 | })
221 | .disposed(by: disposeBag)
222 | """,
223 | install: { view, _, nextStep, stepBag in
224 |
225 | view.animateBackgroundColor(to: .red)
226 | view.animateTransform(to: CATransform3DMakeScale(2.0, 2.0, 1.0))
227 |
228 | view.rx
229 | .pressGesture()
230 | .when(.began)
231 | .subscribe(onNext: { _ in
232 | nextStep()
233 | })
234 | .disposed(by: stepBag)
235 | })
236 |
237 | lazy var panStep: Step = Step(
238 | title: "Drag the square around",
239 | code: """
240 | view.rx
241 | .panGesture()
242 | .when(.changed)
243 | .asTranslation()
244 | .subscribe(onNext: { _ in
245 | // Do something
246 | })
247 | .disposed(by: disposeBag)
248 |
249 | view.rx
250 | .anyGesture(
251 | (.pan(), when: .ended),
252 | (.click(), when: .recognized)
253 | )
254 | .subscribe(onNext: { _ in
255 | // Do something
256 | })
257 | .disposed(by: disposeBag)
258 | """,
259 | install: { view, label, nextStep, stepBag in
260 |
261 | view.animateTransform(to: CATransform3DIdentity)
262 |
263 | view.rx
264 | .panGesture()
265 | .when(.changed)
266 | .asTranslation()
267 | .subscribe(onNext: { translation, _ in
268 | label.stringValue = String(format: "(%.f, %.f)", arguments: [translation.x, translation.y])
269 | view.layer!.transform = CATransform3DMakeTranslation(translation.x, translation.y, 0.0)
270 | })
271 | .disposed(by: stepBag)
272 |
273 | view.rx
274 | .anyGesture(
275 | (.pan(), when: .ended),
276 | (.leftClick(), when: .recognized)
277 | )
278 | .subscribe(onNext: { _ in
279 | nextStep()
280 | })
281 | .disposed(by: stepBag)
282 | })
283 |
284 | lazy var rotateStep: Step = Step(
285 | title: "Rotate the square with your trackpad, or click if you do not have a trackpad",
286 | code: """
287 | view.rx
288 | .rotationGesture()
289 | .when(.changed)
290 | .asRotation()
291 | .subscribe(onNext: { _ in
292 | // Do something
293 | })
294 | .disposed(by: disposeBag)
295 |
296 | view.rx
297 | .anyGesture(
298 | (.rotation(), when: .ended),
299 | (.click(), when: .recognized)
300 | )
301 | .subscribe(onNext: { _ in
302 | // Do something
303 | })
304 | .disposed(by: disposeBag)
305 | """,
306 | install: { view, label, nextStep, stepBag in
307 |
308 | view.animateTransform(to: CATransform3DIdentity)
309 |
310 | view.rx
311 | .rotationGesture()
312 | .when(.changed)
313 | .asRotation()
314 | .subscribe(onNext: { rotation in
315 | label.stringValue = String(format: "%.0fº", rotation * 180 / .pi)
316 | view.layer!.transform = CATransform3DMakeRotation(rotation, 0, 0, 1)
317 | })
318 | .disposed(by: stepBag)
319 |
320 | view.rx
321 | .anyGesture(
322 | (.rotation(), when: .ended),
323 | (.leftClick(), when: .recognized)
324 | )
325 | .subscribe(onNext: { _ in
326 | nextStep()
327 | })
328 | .disposed(by: stepBag)
329 | })
330 |
331 | lazy var magnificationStep: Step = Step(
332 | title: "Pinch the square with your trackpad, or click if you do not have a trackpad",
333 | code: """
334 | view.rx
335 | .magnificationGesture()
336 | .when(.changed)
337 | .asScale()
338 | .subscribe(onNext: { _ in
339 | // Do something
340 | })
341 | .disposed(by: disposeBag)
342 |
343 | view.rx
344 | .anyGesture(
345 | (.magnification(), when: .ended),
346 | (.click(), when: .recognized)
347 | )
348 | .subscribe(onNext: { _ in
349 | // Do something
350 | })
351 | .disposed(by: disposeBag)
352 | """,
353 | install: { view, label, nextStep, stepBag in
354 |
355 | view.animateTransform(to: CATransform3DIdentity)
356 |
357 | view.rx
358 | .magnificationGesture()
359 | .when(.changed)
360 | .asScale()
361 | .subscribe(onNext: { scale in
362 | label.stringValue = String(format: "scale: %.2f", scale)
363 | view.layer!.transform = CATransform3DMakeScale(scale, scale, 1)
364 | })
365 | .disposed(by: stepBag)
366 |
367 | view.rx
368 | .anyGesture(
369 | (.magnification(), when: .ended),
370 | (.leftClick(), when: .recognized)
371 | )
372 | .subscribe(onNext: { _ in
373 | nextStep()
374 | })
375 | .disposed(by: stepBag)
376 | })
377 |
378 | }
379 |
380 | private extension NSView {
381 |
382 | func animateTransform(to transform: CATransform3D) {
383 | let initialTransform = self.layer?.presentation()?.transform ?? self.layer!.model().transform
384 |
385 | let anim = CABasicAnimation(keyPath: "transform")
386 | anim.duration = 0.5
387 | anim.fromValue = NSValue(caTransform3D: initialTransform)
388 | anim.toValue = NSValue(caTransform3D: transform)
389 | self.layer!.add(anim, forKey: nil)
390 | self.layer!.transform = transform
391 | }
392 |
393 | func animateBackgroundColor(to color: NSColor) {
394 | let initialColor = self.layer?.presentation()?.backgroundColor ?? self.layer?.model().backgroundColor
395 |
396 | let anim = CABasicAnimation(keyPath: "backgroundColor")
397 | anim.duration = 0.5
398 | anim.fromValue = initialColor
399 | anim.toValue = color.cgColor
400 | self.layer!.add(anim, forKey: nil)
401 | self.layer!.backgroundColor = color.cgColor
402 | }
403 | }
404 |
--------------------------------------------------------------------------------
/Example/RxGesture.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 5D528E505C4F09640FE69137 /* Pods_RxGesture_iOS_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E0FE7FD951353CF0314F2E /* Pods_RxGesture_iOS_Demo.framework */; };
11 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; };
12 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; };
13 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
14 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; };
15 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
16 | 93A57689D62FEAC950BE2B05 /* Pods_RxGesture_OSX_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A0DE1183287EB1C1B4A27A6 /* Pods_RxGesture_OSX_Demo.framework */; };
17 | 9CBB5C931CA3D9C30089E3EA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBB5C921CA3D9C30089E3EA /* AppDelegate.swift */; };
18 | 9CBB5C951CA3D9C30089E3EA /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBB5C941CA3D9C30089E3EA /* ViewController.swift */; };
19 | 9CBB5C971CA3D9C30089E3EA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9CBB5C961CA3D9C30089E3EA /* Assets.xcassets */; };
20 | 9CBB5C9A1CA3D9C30089E3EA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9CBB5C981CA3D9C30089E3EA /* Main.storyboard */; };
21 | /* End PBXBuildFile section */
22 |
23 | /* Begin PBXFileReference section */
24 | 2318903E5096B0D250136D79 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; };
25 | 47A5D1CA9387C23F09632B82 /* Pods-RxGesture_iOS_Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxGesture_iOS_Demo.release.xcconfig"; path = "Pods/Target Support Files/Pods-RxGesture_iOS_Demo/Pods-RxGesture_iOS_Demo.release.xcconfig"; sourceTree = ""; };
26 | 607FACD01AFB9204008FA782 /* RxGesture_iOS_Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RxGesture_iOS_Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
27 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
28 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
29 | 607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
30 | 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
31 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
32 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
33 | 63BA1167EB70331BB5507B2C /* Pods-RxGesture_OSX_Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxGesture_OSX_Demo.release.xcconfig"; path = "Pods/Target Support Files/Pods-RxGesture_OSX_Demo/Pods-RxGesture_OSX_Demo.release.xcconfig"; sourceTree = ""; };
34 | 6C7E30D81C8E863C3A3EF411 /* Pods-RxGesture_OSX_Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxGesture_OSX_Demo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RxGesture_OSX_Demo/Pods-RxGesture_OSX_Demo.debug.xcconfig"; sourceTree = ""; };
35 | 8A0DE1183287EB1C1B4A27A6 /* Pods_RxGesture_OSX_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RxGesture_OSX_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
36 | 9C94D1DF1CB3F9AC00F94AEE /* RxCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxCocoa.framework; path = "Pods/../build/Debug/Pods-RxGesture_OSX_Demo/RxCocoa.framework"; sourceTree = ""; };
37 | 9C94D1E01CB3F9AC00F94AEE /* RxSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxSwift.framework; path = "Pods/../build/Debug/Pods-RxGesture_OSX_Demo/RxSwift.framework"; sourceTree = ""; };
38 | 9CBB5C901CA3D9C30089E3EA /* RxGesture_OSX_Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RxGesture_OSX_Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
39 | 9CBB5C921CA3D9C30089E3EA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
40 | 9CBB5C941CA3D9C30089E3EA /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
41 | 9CBB5C961CA3D9C30089E3EA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
42 | 9CBB5C991CA3D9C30089E3EA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
43 | 9CBB5C9B1CA3D9C30089E3EA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
44 | A32D46FFF817D17B80E368BB /* RxGesture.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = RxGesture.podspec; path = ../RxGesture.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
45 | A8ACB04E64DDA0D81C1AD26C /* Pods-RxGesture_iOS_Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxGesture_iOS_Demo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RxGesture_iOS_Demo/Pods-RxGesture_iOS_Demo.debug.xcconfig"; sourceTree = ""; };
46 | AEA5E5F8794395306DA818D0 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; };
47 | F8E0FE7FD951353CF0314F2E /* Pods_RxGesture_iOS_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RxGesture_iOS_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
48 | /* End PBXFileReference section */
49 |
50 | /* Begin PBXFrameworksBuildPhase section */
51 | 607FACCD1AFB9204008FA782 /* Frameworks */ = {
52 | isa = PBXFrameworksBuildPhase;
53 | buildActionMask = 2147483647;
54 | files = (
55 | 5D528E505C4F09640FE69137 /* Pods_RxGesture_iOS_Demo.framework in Frameworks */,
56 | );
57 | runOnlyForDeploymentPostprocessing = 0;
58 | };
59 | 9CBB5C8D1CA3D9C30089E3EA /* Frameworks */ = {
60 | isa = PBXFrameworksBuildPhase;
61 | buildActionMask = 2147483647;
62 | files = (
63 | 93A57689D62FEAC950BE2B05 /* Pods_RxGesture_OSX_Demo.framework in Frameworks */,
64 | );
65 | runOnlyForDeploymentPostprocessing = 0;
66 | };
67 | /* End PBXFrameworksBuildPhase section */
68 |
69 | /* Begin PBXGroup section */
70 | 20A9EE12C51FB5E7E9F4C7D5 /* Pods */ = {
71 | isa = PBXGroup;
72 | children = (
73 | 6C7E30D81C8E863C3A3EF411 /* Pods-RxGesture_OSX_Demo.debug.xcconfig */,
74 | 63BA1167EB70331BB5507B2C /* Pods-RxGesture_OSX_Demo.release.xcconfig */,
75 | A8ACB04E64DDA0D81C1AD26C /* Pods-RxGesture_iOS_Demo.debug.xcconfig */,
76 | 47A5D1CA9387C23F09632B82 /* Pods-RxGesture_iOS_Demo.release.xcconfig */,
77 | );
78 | name = Pods;
79 | sourceTree = "";
80 | };
81 | 607FACC71AFB9204008FA782 = {
82 | isa = PBXGroup;
83 | children = (
84 | 607FACF51AFB993E008FA782 /* Podspec Metadata */,
85 | 607FACD21AFB9204008FA782 /* RxGesture iOS Example */,
86 | 9CBB5C911CA3D9C30089E3EA /* RxGesture OSX Example */,
87 | 607FACD11AFB9204008FA782 /* Products */,
88 | DBB6C45CE5FC3994913798D8 /* Frameworks */,
89 | 20A9EE12C51FB5E7E9F4C7D5 /* Pods */,
90 | );
91 | sourceTree = "";
92 | };
93 | 607FACD11AFB9204008FA782 /* Products */ = {
94 | isa = PBXGroup;
95 | children = (
96 | 607FACD01AFB9204008FA782 /* RxGesture_iOS_Demo.app */,
97 | 9CBB5C901CA3D9C30089E3EA /* RxGesture_OSX_Demo.app */,
98 | );
99 | name = Products;
100 | sourceTree = "";
101 | };
102 | 607FACD21AFB9204008FA782 /* RxGesture iOS Example */ = {
103 | isa = PBXGroup;
104 | children = (
105 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */,
106 | 607FACD71AFB9204008FA782 /* ViewController.swift */,
107 | 607FACD91AFB9204008FA782 /* Main.storyboard */,
108 | 607FACDC1AFB9204008FA782 /* Images.xcassets */,
109 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */,
110 | 607FACD31AFB9204008FA782 /* Supporting Files */,
111 | );
112 | name = "RxGesture iOS Example ";
113 | path = RxGesture;
114 | sourceTree = "";
115 | };
116 | 607FACD31AFB9204008FA782 /* Supporting Files */ = {
117 | isa = PBXGroup;
118 | children = (
119 | 607FACD41AFB9204008FA782 /* Info.plist */,
120 | );
121 | name = "Supporting Files";
122 | sourceTree = "";
123 | };
124 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = {
125 | isa = PBXGroup;
126 | children = (
127 | A32D46FFF817D17B80E368BB /* RxGesture.podspec */,
128 | AEA5E5F8794395306DA818D0 /* README.md */,
129 | 2318903E5096B0D250136D79 /* LICENSE */,
130 | );
131 | name = "Podspec Metadata";
132 | sourceTree = "";
133 | };
134 | 9CBB5C911CA3D9C30089E3EA /* RxGesture OSX Example */ = {
135 | isa = PBXGroup;
136 | children = (
137 | 9CBB5C921CA3D9C30089E3EA /* AppDelegate.swift */,
138 | 9CBB5C941CA3D9C30089E3EA /* ViewController.swift */,
139 | 9CBB5C961CA3D9C30089E3EA /* Assets.xcassets */,
140 | 9CBB5C981CA3D9C30089E3EA /* Main.storyboard */,
141 | 9CBB5C9B1CA3D9C30089E3EA /* Info.plist */,
142 | );
143 | name = "RxGesture OSX Example";
144 | path = "RxGesture-OSX";
145 | sourceTree = "";
146 | };
147 | DBB6C45CE5FC3994913798D8 /* Frameworks */ = {
148 | isa = PBXGroup;
149 | children = (
150 | 9C94D1DF1CB3F9AC00F94AEE /* RxCocoa.framework */,
151 | 9C94D1E01CB3F9AC00F94AEE /* RxSwift.framework */,
152 | 8A0DE1183287EB1C1B4A27A6 /* Pods_RxGesture_OSX_Demo.framework */,
153 | F8E0FE7FD951353CF0314F2E /* Pods_RxGesture_iOS_Demo.framework */,
154 | );
155 | name = Frameworks;
156 | sourceTree = "";
157 | };
158 | /* End PBXGroup section */
159 |
160 | /* Begin PBXNativeTarget section */
161 | 607FACCF1AFB9204008FA782 /* RxGesture_iOS_Demo */ = {
162 | isa = PBXNativeTarget;
163 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "RxGesture_iOS_Demo" */;
164 | buildPhases = (
165 | CDB795DBD98169E1348CB0E6 /* [CP] Check Pods Manifest.lock */,
166 | 786B9ECF22A850FF005D335F /* Swiftlint */,
167 | 607FACCC1AFB9204008FA782 /* Sources */,
168 | 607FACCD1AFB9204008FA782 /* Frameworks */,
169 | 607FACCE1AFB9204008FA782 /* Resources */,
170 | 58D78C3A772A244F05D5E0CC /* [CP] Embed Pods Frameworks */,
171 | );
172 | buildRules = (
173 | );
174 | dependencies = (
175 | );
176 | name = RxGesture_iOS_Demo;
177 | productName = RxGesture;
178 | productReference = 607FACD01AFB9204008FA782 /* RxGesture_iOS_Demo.app */;
179 | productType = "com.apple.product-type.application";
180 | };
181 | 9CBB5C8F1CA3D9C30089E3EA /* RxGesture_OSX_Demo */ = {
182 | isa = PBXNativeTarget;
183 | buildConfigurationList = 9CBB5C9E1CA3D9C30089E3EA /* Build configuration list for PBXNativeTarget "RxGesture_OSX_Demo" */;
184 | buildPhases = (
185 | 4884FD709FE61C738647B2EE /* [CP] Check Pods Manifest.lock */,
186 | 9CBB5C8C1CA3D9C30089E3EA /* Sources */,
187 | 9CBB5C8D1CA3D9C30089E3EA /* Frameworks */,
188 | 9CBB5C8E1CA3D9C30089E3EA /* Resources */,
189 | 806AE04460EE07E485B38C35 /* [CP] Embed Pods Frameworks */,
190 | );
191 | buildRules = (
192 | );
193 | dependencies = (
194 | );
195 | name = RxGesture_OSX_Demo;
196 | productName = "RxGesture-OSX";
197 | productReference = 9CBB5C901CA3D9C30089E3EA /* RxGesture_OSX_Demo.app */;
198 | productType = "com.apple.product-type.application";
199 | };
200 | /* End PBXNativeTarget section */
201 |
202 | /* Begin PBXProject section */
203 | 607FACC81AFB9204008FA782 /* Project object */ = {
204 | isa = PBXProject;
205 | attributes = {
206 | LastSwiftUpdateCheck = 0730;
207 | LastUpgradeCheck = 1000;
208 | ORGANIZATIONNAME = CocoaPods;
209 | TargetAttributes = {
210 | 607FACCF1AFB9204008FA782 = {
211 | CreatedOnToolsVersion = 6.3.1;
212 | DevelopmentTeam = JKFCB4CN7C;
213 | LastSwiftMigration = 1020;
214 | ProvisioningStyle = Manual;
215 | };
216 | 9CBB5C8F1CA3D9C30089E3EA = {
217 | CreatedOnToolsVersion = 7.3;
218 | LastSwiftMigration = 0800;
219 | };
220 | };
221 | };
222 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "RxGesture" */;
223 | compatibilityVersion = "Xcode 3.2";
224 | developmentRegion = en;
225 | hasScannedForEncodings = 0;
226 | knownRegions = (
227 | en,
228 | Base,
229 | );
230 | mainGroup = 607FACC71AFB9204008FA782;
231 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */;
232 | projectDirPath = "";
233 | projectRoot = "";
234 | targets = (
235 | 607FACCF1AFB9204008FA782 /* RxGesture_iOS_Demo */,
236 | 9CBB5C8F1CA3D9C30089E3EA /* RxGesture_OSX_Demo */,
237 | );
238 | };
239 | /* End PBXProject section */
240 |
241 | /* Begin PBXResourcesBuildPhase section */
242 | 607FACCE1AFB9204008FA782 /* Resources */ = {
243 | isa = PBXResourcesBuildPhase;
244 | buildActionMask = 2147483647;
245 | files = (
246 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */,
247 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */,
248 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */,
249 | );
250 | runOnlyForDeploymentPostprocessing = 0;
251 | };
252 | 9CBB5C8E1CA3D9C30089E3EA /* Resources */ = {
253 | isa = PBXResourcesBuildPhase;
254 | buildActionMask = 2147483647;
255 | files = (
256 | 9CBB5C971CA3D9C30089E3EA /* Assets.xcassets in Resources */,
257 | 9CBB5C9A1CA3D9C30089E3EA /* Main.storyboard in Resources */,
258 | );
259 | runOnlyForDeploymentPostprocessing = 0;
260 | };
261 | /* End PBXResourcesBuildPhase section */
262 |
263 | /* Begin PBXShellScriptBuildPhase section */
264 | 4884FD709FE61C738647B2EE /* [CP] Check Pods Manifest.lock */ = {
265 | isa = PBXShellScriptBuildPhase;
266 | buildActionMask = 2147483647;
267 | files = (
268 | );
269 | inputPaths = (
270 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
271 | "${PODS_ROOT}/Manifest.lock",
272 | );
273 | name = "[CP] Check Pods Manifest.lock";
274 | outputPaths = (
275 | "$(DERIVED_FILE_DIR)/Pods-RxGesture_OSX_Demo-checkManifestLockResult.txt",
276 | );
277 | runOnlyForDeploymentPostprocessing = 0;
278 | shellPath = /bin/sh;
279 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
280 | showEnvVarsInLog = 0;
281 | };
282 | 58D78C3A772A244F05D5E0CC /* [CP] Embed Pods Frameworks */ = {
283 | isa = PBXShellScriptBuildPhase;
284 | buildActionMask = 2147483647;
285 | files = (
286 | );
287 | inputPaths = (
288 | "${PODS_ROOT}/Target Support Files/Pods-RxGesture_iOS_Demo/Pods-RxGesture_iOS_Demo-frameworks.sh",
289 | "${BUILT_PRODUCTS_DIR}/RxCocoa-iOS/RxCocoa.framework",
290 | "${BUILT_PRODUCTS_DIR}/RxGesture-iOS/RxGesture.framework",
291 | "${BUILT_PRODUCTS_DIR}/RxRelay-iOS/RxRelay.framework",
292 | "${BUILT_PRODUCTS_DIR}/RxSwift-iOS/RxSwift.framework",
293 | );
294 | name = "[CP] Embed Pods Frameworks";
295 | outputPaths = (
296 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework",
297 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxGesture.framework",
298 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxRelay.framework",
299 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwift.framework",
300 | );
301 | runOnlyForDeploymentPostprocessing = 0;
302 | shellPath = /bin/sh;
303 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RxGesture_iOS_Demo/Pods-RxGesture_iOS_Demo-frameworks.sh\"\n";
304 | showEnvVarsInLog = 0;
305 | };
306 | 786B9ECF22A850FF005D335F /* Swiftlint */ = {
307 | isa = PBXShellScriptBuildPhase;
308 | buildActionMask = 2147483647;
309 | files = (
310 | );
311 | inputFileListPaths = (
312 | );
313 | inputPaths = (
314 | );
315 | name = Swiftlint;
316 | outputFileListPaths = (
317 | );
318 | outputPaths = (
319 | );
320 | runOnlyForDeploymentPostprocessing = 0;
321 | shellPath = /bin/sh;
322 | shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
323 | };
324 | 806AE04460EE07E485B38C35 /* [CP] Embed Pods Frameworks */ = {
325 | isa = PBXShellScriptBuildPhase;
326 | buildActionMask = 2147483647;
327 | files = (
328 | );
329 | inputPaths = (
330 | "${PODS_ROOT}/Target Support Files/Pods-RxGesture_OSX_Demo/Pods-RxGesture_OSX_Demo-frameworks.sh",
331 | "${BUILT_PRODUCTS_DIR}/RxCocoa-macOS/RxCocoa.framework",
332 | "${BUILT_PRODUCTS_DIR}/RxGesture-macOS/RxGesture.framework",
333 | "${BUILT_PRODUCTS_DIR}/RxRelay-macOS/RxRelay.framework",
334 | "${BUILT_PRODUCTS_DIR}/RxSwift-macOS/RxSwift.framework",
335 | );
336 | name = "[CP] Embed Pods Frameworks";
337 | outputPaths = (
338 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework",
339 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxGesture.framework",
340 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxRelay.framework",
341 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwift.framework",
342 | );
343 | runOnlyForDeploymentPostprocessing = 0;
344 | shellPath = /bin/sh;
345 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RxGesture_OSX_Demo/Pods-RxGesture_OSX_Demo-frameworks.sh\"\n";
346 | showEnvVarsInLog = 0;
347 | };
348 | CDB795DBD98169E1348CB0E6 /* [CP] Check Pods Manifest.lock */ = {
349 | isa = PBXShellScriptBuildPhase;
350 | buildActionMask = 2147483647;
351 | files = (
352 | );
353 | inputPaths = (
354 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
355 | "${PODS_ROOT}/Manifest.lock",
356 | );
357 | name = "[CP] Check Pods Manifest.lock";
358 | outputPaths = (
359 | "$(DERIVED_FILE_DIR)/Pods-RxGesture_iOS_Demo-checkManifestLockResult.txt",
360 | );
361 | runOnlyForDeploymentPostprocessing = 0;
362 | shellPath = /bin/sh;
363 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
364 | showEnvVarsInLog = 0;
365 | };
366 | /* End PBXShellScriptBuildPhase section */
367 |
368 | /* Begin PBXSourcesBuildPhase section */
369 | 607FACCC1AFB9204008FA782 /* Sources */ = {
370 | isa = PBXSourcesBuildPhase;
371 | buildActionMask = 2147483647;
372 | files = (
373 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */,
374 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */,
375 | );
376 | runOnlyForDeploymentPostprocessing = 0;
377 | };
378 | 9CBB5C8C1CA3D9C30089E3EA /* Sources */ = {
379 | isa = PBXSourcesBuildPhase;
380 | buildActionMask = 2147483647;
381 | files = (
382 | 9CBB5C951CA3D9C30089E3EA /* ViewController.swift in Sources */,
383 | 9CBB5C931CA3D9C30089E3EA /* AppDelegate.swift in Sources */,
384 | );
385 | runOnlyForDeploymentPostprocessing = 0;
386 | };
387 | /* End PBXSourcesBuildPhase section */
388 |
389 | /* Begin PBXVariantGroup section */
390 | 607FACD91AFB9204008FA782 /* Main.storyboard */ = {
391 | isa = PBXVariantGroup;
392 | children = (
393 | 607FACDA1AFB9204008FA782 /* Base */,
394 | );
395 | name = Main.storyboard;
396 | sourceTree = "";
397 | };
398 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = {
399 | isa = PBXVariantGroup;
400 | children = (
401 | 607FACDF1AFB9204008FA782 /* Base */,
402 | );
403 | name = LaunchScreen.xib;
404 | sourceTree = "";
405 | };
406 | 9CBB5C981CA3D9C30089E3EA /* Main.storyboard */ = {
407 | isa = PBXVariantGroup;
408 | children = (
409 | 9CBB5C991CA3D9C30089E3EA /* Base */,
410 | );
411 | name = Main.storyboard;
412 | sourceTree = "";
413 | };
414 | /* End PBXVariantGroup section */
415 |
416 | /* Begin XCBuildConfiguration section */
417 | 607FACED1AFB9204008FA782 /* Debug */ = {
418 | isa = XCBuildConfiguration;
419 | buildSettings = {
420 | ALWAYS_SEARCH_USER_PATHS = NO;
421 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
422 | CLANG_CXX_LIBRARY = "libc++";
423 | CLANG_ENABLE_MODULES = YES;
424 | CLANG_ENABLE_OBJC_ARC = YES;
425 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
426 | CLANG_WARN_BOOL_CONVERSION = YES;
427 | CLANG_WARN_COMMA = YES;
428 | CLANG_WARN_CONSTANT_CONVERSION = YES;
429 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
430 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
431 | CLANG_WARN_EMPTY_BODY = YES;
432 | CLANG_WARN_ENUM_CONVERSION = YES;
433 | CLANG_WARN_INFINITE_RECURSION = YES;
434 | CLANG_WARN_INT_CONVERSION = YES;
435 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
436 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
437 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
438 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
439 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
440 | CLANG_WARN_STRICT_PROTOTYPES = YES;
441 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
442 | CLANG_WARN_UNREACHABLE_CODE = YES;
443 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
444 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
445 | COPY_PHASE_STRIP = NO;
446 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
447 | ENABLE_STRICT_OBJC_MSGSEND = YES;
448 | ENABLE_TESTABILITY = YES;
449 | GCC_C_LANGUAGE_STANDARD = gnu99;
450 | GCC_DYNAMIC_NO_PIC = NO;
451 | GCC_NO_COMMON_BLOCKS = YES;
452 | GCC_OPTIMIZATION_LEVEL = 0;
453 | GCC_PREPROCESSOR_DEFINITIONS = (
454 | "DEBUG=1",
455 | "$(inherited)",
456 | );
457 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
458 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
459 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
460 | GCC_WARN_UNDECLARED_SELECTOR = YES;
461 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
462 | GCC_WARN_UNUSED_FUNCTION = YES;
463 | GCC_WARN_UNUSED_VARIABLE = YES;
464 | IPHONEOS_DEPLOYMENT_TARGET = 8.3;
465 | MTL_ENABLE_DEBUG_INFO = YES;
466 | ONLY_ACTIVE_ARCH = YES;
467 | SDKROOT = iphoneos;
468 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
469 | SWIFT_SWIFT3_OBJC_INFERENCE = On;
470 | SWIFT_VERSION = 5.0;
471 | };
472 | name = Debug;
473 | };
474 | 607FACEE1AFB9204008FA782 /* Release */ = {
475 | isa = XCBuildConfiguration;
476 | buildSettings = {
477 | ALWAYS_SEARCH_USER_PATHS = NO;
478 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
479 | CLANG_CXX_LIBRARY = "libc++";
480 | CLANG_ENABLE_MODULES = YES;
481 | CLANG_ENABLE_OBJC_ARC = YES;
482 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
483 | CLANG_WARN_BOOL_CONVERSION = YES;
484 | CLANG_WARN_COMMA = YES;
485 | CLANG_WARN_CONSTANT_CONVERSION = YES;
486 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
487 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
488 | CLANG_WARN_EMPTY_BODY = YES;
489 | CLANG_WARN_ENUM_CONVERSION = YES;
490 | CLANG_WARN_INFINITE_RECURSION = YES;
491 | CLANG_WARN_INT_CONVERSION = YES;
492 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
493 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
494 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
495 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
496 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
497 | CLANG_WARN_STRICT_PROTOTYPES = YES;
498 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
499 | CLANG_WARN_UNREACHABLE_CODE = YES;
500 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
501 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
502 | COPY_PHASE_STRIP = NO;
503 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
504 | ENABLE_NS_ASSERTIONS = NO;
505 | ENABLE_STRICT_OBJC_MSGSEND = YES;
506 | GCC_C_LANGUAGE_STANDARD = gnu99;
507 | GCC_NO_COMMON_BLOCKS = YES;
508 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
509 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
510 | GCC_WARN_UNDECLARED_SELECTOR = YES;
511 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
512 | GCC_WARN_UNUSED_FUNCTION = YES;
513 | GCC_WARN_UNUSED_VARIABLE = YES;
514 | IPHONEOS_DEPLOYMENT_TARGET = 8.3;
515 | MTL_ENABLE_DEBUG_INFO = NO;
516 | SDKROOT = iphoneos;
517 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
518 | SWIFT_SWIFT3_OBJC_INFERENCE = On;
519 | SWIFT_VERSION = 5.0;
520 | VALIDATE_PRODUCT = YES;
521 | };
522 | name = Release;
523 | };
524 | 607FACF01AFB9204008FA782 /* Debug */ = {
525 | isa = XCBuildConfiguration;
526 | baseConfigurationReference = A8ACB04E64DDA0D81C1AD26C /* Pods-RxGesture_iOS_Demo.debug.xcconfig */;
527 | buildSettings = {
528 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
529 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
530 | CODE_SIGN_STYLE = Manual;
531 | DEVELOPMENT_TEAM = JKFCB4CN7C;
532 | INFOPLIST_FILE = RxGesture/Info.plist;
533 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
534 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
535 | MODULE_NAME = ExampleApp;
536 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
537 | PRODUCT_NAME = "$(TARGET_NAME)";
538 | PROVISIONING_PROFILE_SPECIFIER = "Wildcard Development";
539 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
540 | SWIFT_VERSION = 5.0;
541 | };
542 | name = Debug;
543 | };
544 | 607FACF11AFB9204008FA782 /* Release */ = {
545 | isa = XCBuildConfiguration;
546 | baseConfigurationReference = 47A5D1CA9387C23F09632B82 /* Pods-RxGesture_iOS_Demo.release.xcconfig */;
547 | buildSettings = {
548 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
549 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
550 | CODE_SIGN_STYLE = Manual;
551 | DEVELOPMENT_TEAM = JKFCB4CN7C;
552 | INFOPLIST_FILE = RxGesture/Info.plist;
553 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
554 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
555 | MODULE_NAME = ExampleApp;
556 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
557 | PRODUCT_NAME = "$(TARGET_NAME)";
558 | PROVISIONING_PROFILE_SPECIFIER = "Wildcard Development";
559 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
560 | SWIFT_VERSION = 5.0;
561 | };
562 | name = Release;
563 | };
564 | 9CBB5C9C1CA3D9C30089E3EA /* Debug */ = {
565 | isa = XCBuildConfiguration;
566 | baseConfigurationReference = 6C7E30D81C8E863C3A3EF411 /* Pods-RxGesture_OSX_Demo.debug.xcconfig */;
567 | buildSettings = {
568 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
569 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
570 | CLANG_ANALYZER_NONNULL = YES;
571 | CODE_SIGN_IDENTITY = "-";
572 | COMBINE_HIDPI_IMAGES = YES;
573 | DEBUG_INFORMATION_FORMAT = dwarf;
574 | INFOPLIST_FILE = "RxGesture-OSX/Info.plist";
575 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
576 | MACOSX_DEPLOYMENT_TARGET = 10.10;
577 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.RxGesture-OSX-Demo";
578 | PRODUCT_NAME = "$(TARGET_NAME)";
579 | SDKROOT = macosx;
580 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
581 | SWIFT_VERSION = 5.0;
582 | };
583 | name = Debug;
584 | };
585 | 9CBB5C9D1CA3D9C30089E3EA /* Release */ = {
586 | isa = XCBuildConfiguration;
587 | baseConfigurationReference = 63BA1167EB70331BB5507B2C /* Pods-RxGesture_OSX_Demo.release.xcconfig */;
588 | buildSettings = {
589 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
590 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
591 | CLANG_ANALYZER_NONNULL = YES;
592 | CODE_SIGN_IDENTITY = "-";
593 | COMBINE_HIDPI_IMAGES = YES;
594 | INFOPLIST_FILE = "RxGesture-OSX/Info.plist";
595 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
596 | MACOSX_DEPLOYMENT_TARGET = 10.10;
597 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.RxGesture-OSX-Demo";
598 | PRODUCT_NAME = "$(TARGET_NAME)";
599 | SDKROOT = macosx;
600 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
601 | SWIFT_VERSION = 5.0;
602 | };
603 | name = Release;
604 | };
605 | /* End XCBuildConfiguration section */
606 |
607 | /* Begin XCConfigurationList section */
608 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "RxGesture" */ = {
609 | isa = XCConfigurationList;
610 | buildConfigurations = (
611 | 607FACED1AFB9204008FA782 /* Debug */,
612 | 607FACEE1AFB9204008FA782 /* Release */,
613 | );
614 | defaultConfigurationIsVisible = 0;
615 | defaultConfigurationName = Release;
616 | };
617 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "RxGesture_iOS_Demo" */ = {
618 | isa = XCConfigurationList;
619 | buildConfigurations = (
620 | 607FACF01AFB9204008FA782 /* Debug */,
621 | 607FACF11AFB9204008FA782 /* Release */,
622 | );
623 | defaultConfigurationIsVisible = 0;
624 | defaultConfigurationName = Release;
625 | };
626 | 9CBB5C9E1CA3D9C30089E3EA /* Build configuration list for PBXNativeTarget "RxGesture_OSX_Demo" */ = {
627 | isa = XCConfigurationList;
628 | buildConfigurations = (
629 | 9CBB5C9C1CA3D9C30089E3EA /* Debug */,
630 | 9CBB5C9D1CA3D9C30089E3EA /* Release */,
631 | );
632 | defaultConfigurationIsVisible = 0;
633 | defaultConfigurationName = Release;
634 | };
635 | /* End XCConfigurationList section */
636 | };
637 | rootObject = 607FACC81AFB9204008FA782 /* Project object */;
638 | }
639 |
--------------------------------------------------------------------------------
/Example/RxGesture.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/Example/RxGesture.xcodeproj/xcshareddata/xcschemes/RxGesture_iOS_Demo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
57 |
63 |
64 |
65 |
66 |
67 |
73 |
74 |
75 |
76 |
77 |
78 |
88 |
90 |
96 |
97 |
98 |
99 |
100 |
101 |
107 |
109 |
115 |
116 |
117 |
118 |
120 |
121 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/Example/RxGesture.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/RxGesture.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/RxGesture/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // RxGesture
4 | //
5 | // Created by Marin Todorov on 03/22/2016.
6 | // Copyright (c) 2016 Marin Todorov. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 | var window: UIWindow?
14 | }
15 |
--------------------------------------------------------------------------------
/Example/RxGesture/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/Example/RxGesture/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/Example/RxGesture/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "scale" : "1x",
46 | "size" : "1024x1024"
47 | }
48 | ],
49 | "info" : {
50 | "author" : "xcode",
51 | "version" : 1
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Example/RxGesture/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 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Example/RxGesture/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // RxGesture
4 | //
5 | // Created by Marin Todorov on 03/22/2016.
6 | // Copyright (c) 2016 Marin Todorov. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | import RxSwift
12 | import RxGesture
13 |
14 | class Step {
15 | enum Action { case previous, next }
16 | typealias InitialState = (alpha: CGFloat, color: UIColor, transform: CGAffineTransform)
17 | let title: String
18 | let code: String
19 | let initialState: InitialState
20 | let install: (UIView, UILabel, @escaping () -> Void, DisposeBag) -> Void
21 |
22 | init(title: String, code: String, initialState: InitialState, install: @escaping (UIView, UILabel, @escaping () -> Void, DisposeBag) -> Void) {
23 | self.title = title
24 | self.code = code
25 | self.initialState = initialState
26 | self.install = install
27 | }
28 | }
29 |
30 | class ViewController: UIViewController {
31 |
32 | @IBOutlet private var myView: UIView!
33 | @IBOutlet private var myViewText: UILabel!
34 | @IBOutlet private var info: UILabel!
35 | @IBOutlet private var code: UITextView!
36 |
37 | private let nextStepObserver = PublishSubject()
38 | private let bag = DisposeBag()
39 | private var stepBag = DisposeBag()
40 |
41 | override func viewDidLoad() {
42 | super.viewDidLoad()
43 |
44 | navigationController?.navigationBar.shadowImage = UIImage()
45 | let steps: [Step] = [
46 | tapStep,
47 | doubleTapStep,
48 | swipeDownStep,
49 | swipeHorizontallyStep,
50 | longPressStep,
51 | touchDownStep,
52 | forceTouchStep,
53 | panStep,
54 | pinchStep,
55 | rotateStep,
56 | transformStep
57 | ]
58 |
59 | func newIndex(for index: Int, action: Step.Action) -> Int {
60 | switch action {
61 | case .previous:
62 | return (steps.count + index - 1) % steps.count
63 | case .next:
64 | return (steps.count + index + 1) % steps.count
65 | }
66 | }
67 |
68 | nextStepObserver
69 | .scan(0, accumulator: newIndex)
70 | .startWith(0)
71 | .map { (steps[$0], $0) }
72 | .subscribe(onNext: { [unowned self] step, index in
73 | self.updateStep(step, at: index)
74 | })
75 | .disposed(by: bag)
76 | }
77 |
78 | override func viewDidAppear(_ animated: Bool) {
79 | super.viewDidAppear(animated)
80 | guard let superview = myView.superview, let window = view.window else {
81 | return
82 | }
83 | window.addSubview(myView)
84 | myView.centerXAnchor.constraint(equalTo: superview.centerXAnchor).isActive = true
85 | myView.centerYAnchor.constraint(equalTo: superview.centerYAnchor).isActive = true
86 | }
87 |
88 | @IBAction func previousStep(_ sender: Any) {
89 | nextStepObserver.onNext(.previous)
90 | }
91 |
92 | @IBAction func nextStep(_ sender: Any) {
93 | nextStepObserver.onNext(.next)
94 | }
95 |
96 | func updateStep(_ step: Step, at index: Int) {
97 | stepBag = DisposeBag()
98 |
99 | info.text = "\(index + 1). " + step.title
100 | code.text = step.code
101 |
102 | myViewText.text = nil
103 | myViewText.numberOfLines = 1
104 |
105 | UIView.animate(withDuration: 0.5, delay: 0, options: .beginFromCurrentState) {
106 | self.myView.alpha = step.initialState.alpha
107 | self.myView.backgroundColor = step.initialState.color
108 | self.myView.transform = step.initialState.transform
109 | }
110 |
111 | step.install(myView, myViewText, { [nextStepObserver] in nextStepObserver.onNext(.next) }, stepBag)
112 |
113 | print("active gestures: \(myView.gestureRecognizers?.count ?? 0)")
114 | }
115 |
116 | lazy var tapStep: Step = Step(
117 | title: "Tap the red square",
118 | code: """
119 | view.rx
120 | .tapGesture()
121 | .when(.recognized)
122 | .subscribe(onNext: { _ in
123 | // Do something
124 | })
125 | .disposed(by: disposeBag)
126 | """,
127 | initialState: (1.0, .red, .identity),
128 | install: { view, _, nextStep, stepBag in
129 | view.rx
130 | .tapGesture()
131 | .when(.recognized)
132 | .subscribe(onNext: { _ in
133 | nextStep()
134 | })
135 | .disposed(by: stepBag)
136 | })
137 |
138 | lazy var doubleTapStep: Step = Step(
139 | title: "Double tap the green square",
140 | code: """
141 | view.rx
142 | .tapGesture() { gesture, _ in
143 | gesture.numberOfTapsRequired = 2
144 | }
145 | .when(.recognized)
146 | .subscribe(onNext: { _ in
147 | // Do something
148 | })
149 | .disposed(by: disposeBag)
150 | """,
151 | initialState: (1.0, .green, .identity),
152 | install: { view, _, nextStep, stepBag in
153 | view.rx
154 | .tapGesture { gesture, _ in
155 | gesture.numberOfTapsRequired = 2
156 | }
157 | .when(.recognized)
158 | .subscribe(onNext: { _ in
159 | nextStep()
160 | })
161 | .disposed(by: stepBag)
162 | })
163 |
164 | lazy var swipeDownStep: Step = Step(
165 | title: "Swipe the blue square down",
166 | code: """
167 | view.rx
168 | .swipeGesture(.down)
169 | .when(.recognized)
170 | .subscribe(onNext: { _ in
171 | // Do something
172 | })
173 | .disposed(by: disposeBag)
174 | """,
175 | initialState: (1.0, .blue, .identity),
176 | install: { view, _, nextStep, stepBag in
177 | view.rx
178 | .swipeGesture(.down)
179 | .when(.recognized)
180 | .subscribe(onNext: { _ in
181 | nextStep()
182 | })
183 | .disposed(by: stepBag)
184 | })
185 |
186 | lazy var swipeHorizontallyStep: Step = Step(
187 | title: "Swipe horizontally the blue square (e.g. left or right)",
188 | code: """
189 | view.rx
190 | .swipeGesture(.left, .right)
191 | .when(.recognized)
192 | .subscribe(onNext: { _ in
193 | // Do something
194 | })
195 | .disposed(by: disposeBag)
196 | """,
197 | initialState: (1.0, .blue, CGAffineTransform(scaleX: 1.0, y: 2.0)),
198 | install: { view, _, nextStep, stepBag in
199 | view.rx
200 | .swipeGesture(.left, .right)
201 | .when(.recognized)
202 | .subscribe(onNext: { _ in
203 | nextStep()
204 | })
205 | .disposed(by: stepBag)
206 | })
207 |
208 | lazy var longPressStep: Step = Step(
209 | title: "Do a long press",
210 | code: """
211 | view.rx
212 | .longPressGesture()
213 | .when(.began)
214 | .subscribe(onNext: { _ in
215 | // Do something
216 | })
217 | .disposed(by: disposeBag)
218 | """,
219 | initialState: (1.0, .blue, CGAffineTransform(scaleX: 2.0, y: 2.0)),
220 | install: { view, _, nextStep, stepBag in
221 | view.rx
222 | .longPressGesture()
223 | .when(.began)
224 | .subscribe(onNext: { _ in
225 | nextStep()
226 | })
227 | .disposed(by: stepBag)
228 | })
229 |
230 | lazy var touchDownStep: Step = Step(
231 | title: "Touch down the view",
232 | code: """
233 | view.rx
234 | .touchDownGesture()
235 | .when(.began)
236 | .subscribe(onNext: { _ in
237 | // Do something
238 | })
239 | .disposed(by: disposeBag)
240 | """,
241 | initialState: (1.0, .green, .identity),
242 | install: { view, _, nextStep, stepBag in
243 | view.rx
244 | .touchDownGesture()
245 | .when(.began)
246 | .subscribe(onNext: { _ in
247 | nextStep()
248 | })
249 | .disposed(by: stepBag)
250 | })
251 |
252 | @available(iOS 9.0, *)
253 | lazy var forceTouchStep: Step = Step(
254 | title: "Force Touch the view",
255 | code: """
256 | let forceTouch = view.rx
257 | .forceTouchGesture()
258 | .share(replay: 1)
259 |
260 | forceTouch
261 | .asForce()
262 | .subscribe(onNext: { force in
263 | // Do something
264 | })
265 | .disposed(by: stepBag)
266 |
267 | forceTouch
268 | .when(.ended)
269 | .subscribe(onNext: { _ in
270 | // Do something
271 | })
272 | .disposed(by: stepBag)
273 | """,
274 | initialState: (0.25, .red, .identity),
275 | install: { view, label, nextStep, stepBag in
276 | let forceTouch = view.rx
277 | .forceTouchGesture()
278 | .share(replay: 1)
279 |
280 | forceTouch
281 | .when(.possible, .began, .changed)
282 | .subscribe(onNext: { [unowned view] touch in
283 | let max = touch.maximumPossibleForce
284 | let percent = max > 0 ? touch.force / max : 0
285 | view.alpha = percent > 0.75 ? 1.0 : 0.25 + (0.5 * percent)
286 | label.text = String(format: "%.0f%%", percent * 100)
287 | })
288 | .disposed(by: stepBag)
289 |
290 | forceTouch
291 | .when(.ended)
292 | .subscribe(onNext: { _ in
293 | nextStep()
294 | })
295 | .disposed(by: stepBag)
296 |
297 | self.makeImpact(on: forceTouch, stepBag: stepBag)
298 | })
299 |
300 | lazy var panStep: Step = Step(
301 | title: "Drag the square to a different location",
302 | code: """
303 | let panGesture = view.rx
304 | .panGesture()
305 | .share(replay: 1)
306 |
307 | panGesture
308 | .when(.changed)
309 | .asTranslation()
310 | .subscribe(onNext: { _ in
311 | // Do something
312 | })
313 | .disposed(by: disposeBag)
314 |
315 | panGesture
316 | .when(.ended)
317 | .subscribe(onNext: { _ in
318 | // Do something
319 | })
320 | .disposed(by: disposeBag)
321 | """,
322 | initialState: (1.0, .blue, .identity),
323 | install: { view, label, nextStep, stepBag in
324 | let panGesture = view.rx
325 | .panGesture()
326 | .share(replay: 1)
327 |
328 | panGesture
329 | .when(.possible, .began, .changed)
330 | .asTranslation()
331 | .subscribe(onNext: { translation, _ in
332 | label.text = String(format: "(%.2f, %.2f)", translation.x, translation.y)
333 | view.transform = CGAffineTransform(translationX: translation.x, y: translation.y)
334 | })
335 | .disposed(by: stepBag)
336 |
337 | panGesture
338 | .when(.ended)
339 | .subscribe(onNext: { _ in
340 | nextStep()
341 | })
342 | .disposed(by: stepBag)
343 | })
344 |
345 | lazy var rotateStep: Step = Step(
346 | title: "Rotate the square",
347 | code: """
348 | let rotationGesture = view.rx
349 | .rotationGesture()
350 | .share(replay: 1)
351 |
352 | rotationGesture
353 | .when(.changed)
354 | .asRotation()
355 | .subscribe(onNext: { _ in
356 | // Do something
357 | })
358 | .disposed(by: disposeBag)
359 |
360 | rotationGesture
361 | .when(.ended)
362 | .subscribe(onNext: { _ in
363 | // Do something
364 | })
365 | .disposed(by: disposeBag)
366 | """,
367 | initialState: (1.0, .blue, .identity),
368 | install: { view, label, nextStep, stepBag in
369 | let rotationGesture = view.rx
370 | .rotationGesture()
371 | .share(replay: 1)
372 |
373 | rotationGesture
374 | .when(.possible, .began, .changed)
375 | .asRotation()
376 | .subscribe(onNext: { rotation, _ in
377 | label.text = String(format: "%.fº", rotation * 180 / .pi)
378 | view.transform = CGAffineTransform(rotationAngle: rotation)
379 | })
380 | .disposed(by: stepBag)
381 |
382 | rotationGesture
383 | .when(.ended)
384 | .subscribe(onNext: { _ in
385 | nextStep()
386 | })
387 | .disposed(by: stepBag)
388 | })
389 |
390 | lazy var pinchStep: Step = Step(
391 | title: "Pinch the square",
392 | code: """
393 | let pinchGesture = view.rx.pinchGesture().share(replay: 1)
394 |
395 | pinchGesture
396 | .when(.changed)
397 | .asScale()
398 | .subscribe(onNext: { _ in
399 | // Do something
400 | })
401 | .disposed(by: disposeBag)
402 |
403 | pinchGesture
404 | .when(.ended)
405 | .subscribe(onNext: { _ in
406 | // Do something
407 | })
408 | .disposed(by: disposeBag)
409 | """,
410 | initialState: (1.0, .blue, .identity),
411 | install: { view, label, nextStep, stepBag in
412 | let pinchGesture = view.rx
413 | .pinchGesture()
414 | .share(replay: 1)
415 |
416 | pinchGesture
417 | .when(.possible, .began, .changed)
418 | .asScale()
419 | .subscribe(onNext: { scale, _ in
420 | label.text = String(format: "x%.2f", scale)
421 | view.transform = CGAffineTransform(scaleX: scale, y: scale)
422 | })
423 | .disposed(by: stepBag)
424 |
425 | pinchGesture
426 | .when(.ended)
427 | .subscribe(onNext: { _ in
428 | nextStep()
429 | })
430 | .disposed(by: stepBag)
431 | })
432 |
433 | lazy var transformStep: Step = Step(
434 | title: "Transform the square",
435 | code: """
436 | let transformGestures = view.rx.transformGestures().share(replay: 1)
437 |
438 | transformGestures
439 | .when(.changed)
440 | .asTransform()
441 | .subscribe(onNext: { _ in
442 | // Do something
443 | })
444 | .disposed(by: disposeBag)
445 |
446 | transformGestures
447 | .when(.ended)
448 | .subscribe(onNext: { _ in
449 | // Do something
450 | })
451 | .disposed(by: disposeBag)
452 | """,
453 | initialState: (1.0, .blue, .identity),
454 | install: { view, label, nextStep, stepBag in
455 | let transformGestures = view.rx
456 | .transformGestures()
457 | .share(replay: 1)
458 |
459 | transformGestures
460 | .when(.possible, .began, .changed)
461 | .asTransform()
462 | .subscribe(onNext: { transform, _ in
463 | label.numberOfLines = 3
464 | label.text = String(format: "[%.2f, %.2f,\n%.2f, %.2f,\n%.2f, %.2f]", transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty)
465 | view.transform = transform
466 | })
467 | .disposed(by: stepBag)
468 |
469 | transformGestures
470 | .when(.ended)
471 | .subscribe(onNext: { _ in
472 | nextStep()
473 | })
474 | .disposed(by: stepBag)
475 | })
476 |
477 | private func makeImpact(on forceTouch: Observable, stepBag: DisposeBag) {
478 | // It looks like #available(iOS 10.0, *) is ignored in the lazy var declaration ¯\_(ツ)_/¯
479 |
480 | guard #available(iOS 10.0, *) else { return }
481 | forceTouch
482 | .map { ($0.force / $0.maximumPossibleForce) > 0.75 ? UIImpactFeedbackGenerator.FeedbackStyle.medium : .light }
483 | .distinctUntilChanged()
484 | .skip(1)
485 | .subscribe(onNext: { style in
486 | UIImpactFeedbackGenerator(style: style).impactOccurred()
487 | })
488 | .disposed(by: stepBag)
489 | }
490 | }
491 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'cocoapods', '~> 1.10'
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.3)
5 | activesupport (5.2.4.4)
6 | concurrent-ruby (~> 1.0, >= 1.0.2)
7 | i18n (>= 0.7, < 2)
8 | minitest (~> 5.1)
9 | tzinfo (~> 1.1)
10 | addressable (2.8.0)
11 | public_suffix (>= 2.0.2, < 5.0)
12 | algoliasearch (1.27.5)
13 | httpclient (~> 2.8, >= 2.8.3)
14 | json (>= 1.5.1)
15 | atomos (0.1.3)
16 | claide (1.0.3)
17 | cocoapods (1.10.0)
18 | addressable (~> 2.6)
19 | claide (>= 1.0.2, < 2.0)
20 | cocoapods-core (= 1.10.0)
21 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
22 | cocoapods-downloader (>= 1.4.0, < 2.0)
23 | cocoapods-plugins (>= 1.0.0, < 2.0)
24 | cocoapods-search (>= 1.0.0, < 2.0)
25 | cocoapods-trunk (>= 1.4.0, < 2.0)
26 | cocoapods-try (>= 1.1.0, < 2.0)
27 | colored2 (~> 3.1)
28 | escape (~> 0.0.4)
29 | fourflusher (>= 2.3.0, < 3.0)
30 | gh_inspector (~> 1.0)
31 | molinillo (~> 0.6.6)
32 | nap (~> 1.0)
33 | ruby-macho (~> 1.4)
34 | xcodeproj (>= 1.19.0, < 2.0)
35 | cocoapods-core (1.10.0)
36 | activesupport (> 5.0, < 6)
37 | addressable (~> 2.6)
38 | algoliasearch (~> 1.0)
39 | concurrent-ruby (~> 1.1)
40 | fuzzy_match (~> 2.0.4)
41 | nap (~> 1.0)
42 | netrc (~> 0.11)
43 | public_suffix
44 | typhoeus (~> 1.0)
45 | cocoapods-deintegrate (1.0.4)
46 | cocoapods-downloader (1.6.3)
47 | cocoapods-plugins (1.0.0)
48 | nap
49 | cocoapods-search (1.0.0)
50 | cocoapods-trunk (1.5.0)
51 | nap (>= 0.8, < 2.0)
52 | netrc (~> 0.11)
53 | cocoapods-try (1.2.0)
54 | colored2 (3.1.2)
55 | concurrent-ruby (1.1.7)
56 | escape (0.0.4)
57 | ethon (0.12.0)
58 | ffi (>= 1.3.0)
59 | ffi (1.14.2)
60 | fourflusher (2.3.1)
61 | fuzzy_match (2.0.4)
62 | gh_inspector (1.1.3)
63 | httpclient (2.8.3)
64 | i18n (1.8.6)
65 | concurrent-ruby (~> 1.0)
66 | json (2.5.1)
67 | minitest (5.14.2)
68 | molinillo (0.6.6)
69 | nanaimo (0.3.0)
70 | nap (1.1.0)
71 | netrc (0.11.0)
72 | public_suffix (4.0.6)
73 | ruby-macho (1.4.0)
74 | thread_safe (0.3.6)
75 | typhoeus (1.4.0)
76 | ethon (>= 0.9.0)
77 | tzinfo (1.2.9)
78 | thread_safe (~> 0.1)
79 | xcodeproj (1.19.0)
80 | CFPropertyList (>= 2.3.3, < 4.0)
81 | atomos (~> 0.1.3)
82 | claide (>= 1.0.2, < 2.0)
83 | colored2 (~> 3.1)
84 | nanaimo (~> 0.3.0)
85 |
86 | PLATFORMS
87 | ruby
88 |
89 | DEPENDENCIES
90 | cocoapods (~> 1.10)
91 |
92 | BUNDLED WITH
93 | 2.2.4
94 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) RxSwiftCommunity
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.1
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "RxGesture",
6 | products: [
7 | .library(name: "RxGesture", targets: ["RxGesture"])
8 | ],
9 | dependencies: [
10 | .package(url: "https://github.com/ReactiveX/RxSwift.git", .upToNextMajor(from: "6.0.0")),
11 | ],
12 | targets: [
13 | .target(
14 | name: "RxGesture",
15 | dependencies: ["RxSwift", "RxCocoa"],
16 | path: "Pod",
17 | exclude: ["Classes/OSX"]
18 | )
19 | ]
20 | )
21 |
--------------------------------------------------------------------------------
/Pod/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RxSwiftCommunity/RxGesture/e9f94dfd39efe5b2914ac9463d4193b9e340779c/Pod/Assets/.gitkeep
--------------------------------------------------------------------------------
/Pod/Assets/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RxSwiftCommunity/RxGesture/e9f94dfd39efe5b2914ac9463d4193b9e340779c/Pod/Assets/demo.gif
--------------------------------------------------------------------------------
/Pod/Classes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RxSwiftCommunity/RxGesture/e9f94dfd39efe5b2914ac9463d4193b9e340779c/Pod/Classes/.gitkeep
--------------------------------------------------------------------------------
/Pod/Classes/GenericRxGestureRecognizerDelegate.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #if os(iOS)
22 | import UIKit
23 | #elseif os(OSX)
24 | import AppKit
25 | #endif
26 | import RxSwift
27 | import RxCocoa
28 |
29 | public struct GestureRecognizerDelegatePolicy {
30 | public typealias PolicyBody = (PolicyInput) -> Bool
31 |
32 | private let policy: PolicyBody
33 |
34 | private init(policy: @escaping PolicyBody) {
35 | self.policy = policy
36 | }
37 |
38 | public static func custom(_ policy: @escaping PolicyBody)
39 | -> GestureRecognizerDelegatePolicy {
40 | .init(policy: policy)
41 | }
42 |
43 | public static var always: GestureRecognizerDelegatePolicy {
44 | .init { _ in true }
45 | }
46 |
47 | public static var never: GestureRecognizerDelegatePolicy {
48 | .init { _ in false }
49 | }
50 |
51 | public func isPolicyPassing(with args: PolicyInput) -> Bool {
52 | policy(args)
53 | }
54 | }
55 |
56 | public func || (lhs: GestureRecognizerDelegatePolicy, rhs: GestureRecognizerDelegatePolicy) -> GestureRecognizerDelegatePolicy {
57 | .custom { input in
58 | lhs.isPolicyPassing(with: input) || rhs.isPolicyPassing(with: input)
59 | }
60 | }
61 |
62 | public func && (lhs: GestureRecognizerDelegatePolicy, rhs: GestureRecognizerDelegatePolicy) -> GestureRecognizerDelegatePolicy {
63 | .custom { input in
64 | lhs.isPolicyPassing(with: input) && rhs.isPolicyPassing(with: input)
65 | }
66 | }
67 |
68 | public final class GenericRxGestureRecognizerDelegate: NSObject, RxGestureRecognizerDelegate {
69 |
70 | /// Corresponding delegate method: gestureRecognizerShouldBegin(:_)
71 | public var beginPolicy: GestureRecognizerDelegatePolicy = .always
72 |
73 | /// Corresponding delegate method: gestureRecognizer(_:shouldReceive:)
74 | public var touchReceptionPolicy: GestureRecognizerDelegatePolicy<(Gesture, RxGestureTouch)> = .always
75 |
76 | /// Corresponding delegate method: gestureRecognizer(_:shouldBeRequiredToFailBy:)
77 | public var selfFailureRequirementPolicy: GestureRecognizerDelegatePolicy<(Gesture, RxGestureRecognizer)> = .never
78 |
79 | /// Corresponding delegate method: gestureRecognizer(_:shouldRequireFailureOf:)
80 | public var otherFailureRequirementPolicy: GestureRecognizerDelegatePolicy<(Gesture, RxGestureRecognizer)> = .never
81 |
82 | /// Corresponding delegate method: gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)
83 | public var simultaneousRecognitionPolicy: GestureRecognizerDelegatePolicy<(Gesture, RxGestureRecognizer)> = .always
84 |
85 | #if os(iOS)
86 | // Workaround because we can't have stored properties with @available annotation
87 | private var _pressReceptionPolicy: Any?
88 |
89 | /// Corresponding delegate method: gestureRecognizer(_:shouldReceive:)
90 | public var pressReceptionPolicy: GestureRecognizerDelegatePolicy<(Gesture, UIPress)> {
91 | get {
92 | _pressReceptionPolicy as? GestureRecognizerDelegatePolicy<(Gesture, UIPress)> ?? .always
93 | }
94 | set {
95 | _pressReceptionPolicy = newValue
96 | }
97 | }
98 | #endif
99 |
100 | #if os(OSX)
101 | /// Corresponding delegate method: gestureRecognizer(_:shouldAttemptToRecognizeWith:)
102 | public var eventRecognitionAttemptPolicy: GestureRecognizerDelegatePolicy<(Gesture, NSEvent)> = .always
103 | #endif
104 |
105 | public func gestureRecognizerShouldBegin(
106 | _ gestureRecognizer: RxGestureRecognizer
107 | ) -> Bool {
108 | beginPolicy.isPolicyPassing(with: gestureRecognizer as! Gesture)
109 | }
110 |
111 | public func gestureRecognizer(
112 | _ gestureRecognizer: RxGestureRecognizer,
113 | shouldReceive touch: RxGestureTouch
114 | ) -> Bool {
115 | touchReceptionPolicy.isPolicyPassing(
116 | with: (gestureRecognizer as! Gesture, touch)
117 | )
118 | }
119 |
120 | public func gestureRecognizer(
121 | _ gestureRecognizer: RxGestureRecognizer,
122 | shouldRequireFailureOf otherGestureRecognizer: RxGestureRecognizer
123 | ) -> Bool {
124 | otherFailureRequirementPolicy.isPolicyPassing(
125 | with: (gestureRecognizer as! Gesture, otherGestureRecognizer)
126 | )
127 | }
128 |
129 | public func gestureRecognizer(
130 | _ gestureRecognizer: RxGestureRecognizer,
131 | shouldBeRequiredToFailBy otherGestureRecognizer: RxGestureRecognizer
132 | ) -> Bool {
133 | selfFailureRequirementPolicy.isPolicyPassing(
134 | with: (gestureRecognizer as! Gesture, otherGestureRecognizer)
135 | )
136 | }
137 |
138 | public func gestureRecognizer(
139 | _ gestureRecognizer: RxGestureRecognizer,
140 | shouldRecognizeSimultaneouslyWith otherGestureRecognizer: RxGestureRecognizer
141 | ) -> Bool {
142 | simultaneousRecognitionPolicy.isPolicyPassing(
143 | with: (gestureRecognizer as! Gesture, otherGestureRecognizer)
144 | )
145 | }
146 |
147 | #if os(iOS)
148 |
149 | public func gestureRecognizer(
150 | _ gestureRecognizer: RxGestureRecognizer,
151 | shouldReceive press: UIPress
152 | ) -> Bool {
153 | pressReceptionPolicy.isPolicyPassing(
154 | with: (gestureRecognizer as! Gesture, press)
155 | )
156 | }
157 |
158 | #endif
159 |
160 | #if os(OSX)
161 |
162 | public func gestureRecognizer(
163 | _ gestureRecognizer: RxGestureRecognizer,
164 | shouldAttemptToRecognizeWith event: NSEvent
165 | ) -> Bool {
166 | eventRecognitionAttemptPolicy.isPolicyPassing(
167 | with: (gestureRecognizer as! Gesture, event)
168 | )
169 | }
170 |
171 | #endif
172 |
173 | }
174 |
--------------------------------------------------------------------------------
/Pod/Classes/GestureFactory.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 | #if canImport(ObjectiveC)
21 | import RxSwift
22 | import RxCocoa
23 | import ObjectiveC
24 |
25 | public typealias Configuration = (Gesture, GenericRxGestureRecognizerDelegate) -> Void
26 |
27 | public struct Factory {
28 | public let gesture: Gesture
29 | public init(_ configuration: Configuration?) {
30 | let gesture = Gesture()
31 | let delegate = GenericRxGestureRecognizerDelegate()
32 | objc_setAssociatedObject(
33 | gesture,
34 | &gestureRecognizerStrongDelegateKey,
35 | delegate,
36 | .OBJC_ASSOCIATION_RETAIN_NONATOMIC
37 | )
38 | gesture.delegate = delegate
39 | configuration?(gesture, delegate)
40 | self.gesture = gesture
41 | }
42 |
43 | internal func abstracted() -> AnyFactory {
44 | AnyFactory(self.gesture)
45 | }
46 | }
47 |
48 | internal func make(configuration: Configuration? = nil) -> Factory {
49 | Factory(configuration)
50 | }
51 |
52 | public typealias AnyFactory = Factory
53 | extension Factory where Gesture == RxGestureRecognizer {
54 | private init(_ gesture: G) {
55 | self.gesture = gesture
56 | }
57 | }
58 |
59 | private var gestureRecognizerStrongDelegateKey: UInt8 = 0
60 | #endif
61 |
--------------------------------------------------------------------------------
/Pod/Classes/GestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | import RxSwift
22 | import RxCocoa
23 | import struct CoreGraphics.CGPoint
24 |
25 | public typealias LocationInView = (RxGestureView) -> CGPoint
26 |
27 | extension ObservableType where Element: RxGestureRecognizer {
28 |
29 | /**
30 | Filters the observable `GestureRecognizer` events sequence based on the `GestureRecognizer` state.
31 |
32 | - parameter state: An `GestureRecognizerState` that is used to filter the `GestureRecognizer` events sequence.
33 | - returns: An observable `GestureRecognizer` events sequence that only contains events emitted while the `GestureRecognizer`'s state match the given `state`.
34 | */
35 | public func when(_ states: RxGestureRecognizerState...) -> Observable {
36 | filter { gesture in
37 | states.contains(gesture.state)
38 | }
39 | }
40 |
41 | /**
42 | Filters the observable `GestureRecognizer` events sequence based on the `GestureRecognizer` state.
43 |
44 | - parameter state: An `GestureRecognizerState` that is used to filter the `GestureRecognizer` events sequence.
45 | - returns: An observable `GestureRecognizer` events sequence that only contains events emitted while the `GestureRecognizer`'s state match the given `state`.
46 | */
47 | internal func when(_ states: [RxGestureRecognizerState]) -> Observable {
48 | filter { gesture in
49 | states.contains(gesture.state)
50 | }
51 | }
52 |
53 | /**
54 | Maps the observable `GestureRecognizer` events sequence to an observable sequence of points computed as the location in the given `view` of the gesture.
55 |
56 | - parameter view: A `TargetView` value on which the gesture took place.
57 | */
58 | public func asLocation(in view: TargetView = .view) -> Observable {
59 | map { gesture in
60 | gesture.location(in: view.targetView(for: gesture))
61 | }
62 | }
63 |
64 | public func asLocationInView() -> Observable {
65 | map { gesture in
66 | let targetView = gesture.view!
67 | let location = gesture.location(in: targetView)
68 | return { view in
69 | targetView.convert(location, to: view)
70 | }
71 | }
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/Pod/Classes/OSX/NSClickGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 | #if canImport(AppKit) && !targetEnvironment(macCatalyst)
21 | import AppKit
22 | import RxSwift
23 | import RxCocoa
24 |
25 | private func make(mask: Int, configuration: Configuration?) -> Factory {
26 | make {
27 | $0.buttonMask = mask
28 | configuration?($0, $1)
29 | }
30 | }
31 |
32 | public typealias ClickConfiguration = Configuration
33 | public typealias ClickControlEvent = ControlEvent
34 | public typealias ClickObservable = Observable
35 |
36 | extension Factory where Gesture == RxGestureRecognizer {
37 |
38 | /**
39 | Returns an `AnyFactory` for `NSClickGestureRecognizer`
40 | - parameter buttonMask: bitfield of the button(s) required to recognize this click where bit 0 is the primary button, 1 is the secondary button, etc...
41 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
42 | */
43 | public static func click(buttonMask: Int, configuration: ClickConfiguration? = nil) -> AnyFactory {
44 | make(mask: buttonMask, configuration: configuration).abstracted()
45 | }
46 |
47 | /**
48 | Returns an `AnyFactory` for `NSClickGestureRecognizer`
49 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
50 | */
51 | public static func leftClick(configuration: ClickConfiguration? = nil) -> AnyFactory {
52 | click(buttonMask: 0x1, configuration: configuration)
53 | }
54 |
55 | /**
56 | Returns an `AnyFactory` for `NSClickGestureRecognizer`
57 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
58 | */
59 | public static func rightClick(configuration: ClickConfiguration? = nil) -> AnyFactory {
60 | click(buttonMask: 0x2, configuration: configuration)
61 | }
62 | }
63 |
64 | extension Reactive where Base: RxGestureView {
65 |
66 | /**
67 | Returns an observable `NSClickGestureRecognizer` events sequence
68 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
69 | */
70 | public func clickGesture(buttonMask: Int, configuration: ClickConfiguration? = nil) -> ClickControlEvent {
71 | gesture(make(mask: buttonMask, configuration: configuration))
72 | }
73 |
74 | /**
75 | Returns an observable `NSClickGestureRecognizer` events sequence
76 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
77 | */
78 | public func leftClickGesture(configuration: ClickConfiguration? = nil) -> ClickControlEvent {
79 | gesture(make(mask: 0x1, configuration: configuration))
80 | }
81 |
82 | /**
83 | Returns an observable `NSClickGestureRecognizer` events sequence
84 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
85 | */
86 | public func rightClickGesture(configuration: ClickConfiguration? = nil) -> ClickControlEvent {
87 | gesture(make(mask: 0x2, configuration: configuration))
88 | }
89 |
90 | }
91 | #endif
92 |
--------------------------------------------------------------------------------
/Pod/Classes/OSX/NSGestureRecognizer+Rx.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 | #if canImport(AppKit) && !targetEnvironment(macCatalyst)
21 | import AppKit
22 | import RxSwift
23 | import RxCocoa
24 |
25 | private class GestureTarget {
26 |
27 | private var retainedSelf: GestureTarget?
28 |
29 | var handler: (() -> Void)?
30 |
31 | init() {
32 | retainedSelf = self
33 | }
34 |
35 | func dispose() {
36 | retainedSelf = nil
37 | }
38 |
39 | @objc func controlEvent() {
40 | handler?()
41 | }
42 | }
43 |
44 | extension Reactive where Base: NSGestureRecognizer {
45 |
46 | /**
47 | Reactive wrapper for gesture recognizer events.
48 | */
49 | public var event: ControlEvent {
50 | let source: Observable = Observable.create {observer in
51 | MainScheduler.ensureExecutingOnScheduler()
52 |
53 | let control = self.base
54 | control.isEnabled = true
55 |
56 | let gestureTarget = GestureTarget()
57 | gestureTarget.handler = {
58 | observer.on(.next(control))
59 | }
60 |
61 | control.target = gestureTarget
62 | control.action = #selector(GestureTarget.controlEvent)
63 |
64 | return Disposables.create {
65 | if let view = control.view {
66 | view.removeGestureRecognizer(control)
67 | }
68 | gestureTarget.dispose()
69 | }
70 | }.take(until: self.deallocated)
71 |
72 | return ControlEvent(events: source)
73 | }
74 |
75 | }
76 | #endif
77 |
--------------------------------------------------------------------------------
/Pod/Classes/OSX/NSMagnificationGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 | #if canImport(AppKit) && !targetEnvironment(macCatalyst)
21 | import AppKit
22 | import RxSwift
23 | import RxCocoa
24 |
25 | public typealias MagnificationConfiguration = Configuration
26 | public typealias MagnificationControlEvent = ControlEvent
27 | public typealias MagnificationObservable = Observable
28 |
29 | extension Factory where Gesture == RxGestureRecognizer {
30 |
31 | /**
32 | Returns an `AnyFactory` for `NSMagnificationGestureRecognizer`
33 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
34 | */
35 | public static func magnification(configuration: MagnificationConfiguration? = nil) -> AnyFactory {
36 | make(configuration: configuration).abstracted()
37 | }
38 | }
39 |
40 | extension Reactive where Base: RxGestureView {
41 |
42 | /**
43 | Returns an observable `NSMagnificationGestureRecognizer` events sequence
44 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
45 | */
46 | public func magnificationGesture(configuration: MagnificationConfiguration? = nil) -> MagnificationControlEvent {
47 | gesture(make(configuration: configuration))
48 | }
49 | }
50 |
51 | extension ObservableType where Element: NSMagnificationGestureRecognizer {
52 |
53 | /**
54 | Maps the observable `GestureRecognizer` events sequence to an observable sequence of magnification amounts alongside the gesture velocity.
55 | */
56 | public func asMagnification() -> Observable {
57 | self.map { gesture in
58 | gesture.magnification
59 | }
60 | }
61 |
62 | /**
63 | Maps the observable `GestureRecognizer` events sequence to an observable sequence of scale factors relative to the points of the two touches in screen coordinates alongside the gesture velocity.
64 | */
65 | public func asScale() -> Observable {
66 | self.map { gesture in
67 | 1.0 + gesture.magnification
68 | }
69 | }
70 | }
71 | #endif
72 |
--------------------------------------------------------------------------------
/Pod/Classes/OSX/NSPanGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 | #if canImport(AppKit) && !targetEnvironment(macCatalyst)
21 | import AppKit
22 | import RxSwift
23 | import RxCocoa
24 |
25 | public typealias PanConfiguration = Configuration
26 | public typealias PanControlEvent = ControlEvent
27 | public typealias PanObservable = Observable
28 |
29 | extension Factory where Gesture == RxGestureRecognizer {
30 |
31 | /**
32 | Returns an `AnyFactory` for `NSPanGestureRecognizer`
33 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
34 | */
35 | public static func pan(configuration: PanConfiguration? = nil) -> AnyFactory {
36 | make(configuration: configuration).abstracted()
37 | }
38 | }
39 |
40 | extension Reactive where Base: RxGestureView {
41 |
42 | /**
43 | Returns an observable `NSPanGestureRecognizer` events sequence
44 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
45 | */
46 | public func panGesture(configuration: PanConfiguration? = nil) -> PanControlEvent {
47 | gesture(make(configuration: configuration))
48 | }
49 | }
50 |
51 | extension ObservableType where Element: NSPanGestureRecognizer {
52 |
53 | /**
54 | Maps the observable `GestureRecognizer` events sequence to an observable sequence of translation values of the pan gesture in the coordinate system of the specified `view` alongside the gesture velocity.
55 |
56 | - parameter view: A `TargetView` value on which the gesture took place.
57 | */
58 | public func asTranslation(in view: TargetView = .view) -> Observable<(translation: NSPoint, velocity: NSPoint)> {
59 | self.map { gesture in
60 | let view = view.targetView(for: gesture)
61 | return (
62 | gesture.translation(in: view),
63 | gesture.velocity(in: view)
64 | )
65 | }
66 | }
67 | }
68 | #endif
69 |
--------------------------------------------------------------------------------
/Pod/Classes/OSX/NSPressGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 | #if canImport(AppKit) && !targetEnvironment(macCatalyst)
21 | import AppKit
22 | import RxSwift
23 | import RxCocoa
24 |
25 | public typealias PressConfiguration = Configuration
26 | public typealias PressControlEvent = ControlEvent
27 | public typealias PressObservable = Observable
28 |
29 | extension Factory where Gesture == RxGestureRecognizer {
30 |
31 | /**
32 | Returns an `AnyFactory` for `NSPressGestureRecognizer`
33 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
34 | */
35 | public static func press(configuration: PressConfiguration? = nil) -> AnyFactory {
36 | make(configuration: configuration).abstracted()
37 | }
38 | }
39 |
40 | extension Reactive where Base: RxGestureView {
41 |
42 | /**
43 | Returns an observable `NSPressGestureRecognizer` events sequence
44 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
45 | */
46 | public func pressGesture(configuration: PressConfiguration? = nil) -> PressControlEvent {
47 | gesture(make(configuration: configuration))
48 | }
49 | }
50 | #endif
51 |
--------------------------------------------------------------------------------
/Pod/Classes/OSX/NSRotationGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 | #if canImport(AppKit) && !targetEnvironment(macCatalyst)
21 | import AppKit
22 | import RxSwift
23 | import RxCocoa
24 |
25 | public typealias RotationConfiguration = Configuration
26 | public typealias RotationControlEvent = ControlEvent
27 | public typealias RotationObservable = Observable
28 |
29 | extension Factory where Gesture == RxGestureRecognizer {
30 |
31 | /**
32 | Returns an `AnyFactory` for `NSRotationGestureRecognizer`
33 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
34 | */
35 | public static func rotation(configuration: RotationConfiguration? = nil) -> AnyFactory {
36 | make(configuration: configuration).abstracted()
37 | }
38 | }
39 |
40 | extension Reactive where Base: RxGestureView {
41 |
42 | /**
43 | Returns an observable `NSRotationGestureRecognizer` events sequence
44 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
45 | */
46 | public func rotationGesture(configuration: RotationConfiguration? = nil) -> RotationControlEvent {
47 | gesture(make(configuration: configuration))
48 | }
49 | }
50 |
51 | extension ObservableType where Element: NSRotationGestureRecognizer {
52 |
53 | /**
54 | Maps the observable `GestureRecognizer` events sequence to an observable sequence of rotation values of the gesture in radians.
55 | */
56 | public func asRotation() -> Observable {
57 | self.map { gesture in
58 | gesture.rotation
59 | }
60 | }
61 | }
62 | #endif
63 |
--------------------------------------------------------------------------------
/Pod/Classes/SharedTypes.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | import Foundation
22 |
23 | #if os(iOS)
24 | import UIKit
25 | public typealias RxGestureTouch = UITouch
26 | public typealias RxGestureRecognizer = UIGestureRecognizer
27 | public typealias RxGestureRecognizerState = UIGestureRecognizer.State
28 | public typealias RxGestureRecognizerDelegate = UIGestureRecognizerDelegate
29 | public typealias RxGestureView = UIView
30 | public typealias RxGesturePoint = CGPoint
31 | #elseif os(OSX)
32 | import AppKit
33 | public typealias RxGestureTouch = NSTouch
34 | public typealias RxGestureRecognizer = NSGestureRecognizer
35 | public typealias RxGestureRecognizerState = NSGestureRecognizer.State
36 | public typealias RxGestureRecognizerDelegate = NSGestureRecognizerDelegate
37 | public typealias RxGestureView = NSView
38 | public typealias RxGesturePoint = NSPoint
39 | #endif
40 |
41 | public enum TargetView {
42 | /// The target view will be the gestureRecognizer's view
43 | case view
44 |
45 | /// The target view will be the gestureRecognizer's view's superview
46 | case superview
47 |
48 | /// The target view will be the gestureRecognizer's view's window
49 | case window
50 |
51 | /// The target view will be the given view
52 | case this(RxGestureView)
53 |
54 | public func targetView(for gestureRecognizer: RxGestureRecognizer) -> RxGestureView? {
55 | switch self {
56 | case .view:
57 | return gestureRecognizer.view
58 | case .superview:
59 | return gestureRecognizer.view?.superview
60 | case .window:
61 | #if os(iOS)
62 | return gestureRecognizer.view?.window
63 | #elseif os(OSX)
64 | return gestureRecognizer.view?.window?.contentView
65 | #endif
66 | case let .this(view):
67 | return view
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Pod/Classes/View+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | import RxSwift
22 | import RxCocoa
23 | import Dispatch
24 |
25 | extension Reactive where Base: RxGestureView {
26 |
27 | /**
28 | Reactive wrapper for multiple view gesture recognizers.
29 | It automatically attaches the gesture recognizers to the receiver view.
30 | The value the `Observable` emits is the gesture recognizer itself.
31 |
32 | rx.anyGesture can't error and is subscribed/observed on main scheduler.
33 | - parameter factories: a `(Factory + state)` collection you want to use to create the `GestureRecognizers` to add and observe
34 | - returns: a `ControlEvent` that re-emit the gesture recognizer itself
35 | */
36 | public func anyGesture(_ factories: (AnyFactory, when: RxGestureRecognizerState)...) -> ControlEvent {
37 | let observables = factories.map { gesture, state in
38 | self.gesture(gesture).when(state).asObservable() as Observable
39 | }
40 | let source = Observable.from(observables).merge()
41 | return ControlEvent(events: source)
42 | }
43 |
44 | /**
45 | Reactive wrapper for multiple view gesture recognizers.
46 | It automatically attaches the gesture recognizers to the receiver view.
47 | The value the `Observable` emits is the gesture recognizer itself.
48 |
49 | rx.anyGesture can't error and is subscribed/observed on main scheduler.
50 | - parameter factories: a `Factory` collection you want to use to create the `GestureRecognizers` to add and observe
51 | - returns: a `ControlEvent` that re-emit the gesture recognizer itself
52 | */
53 | public func anyGesture(_ factories: AnyFactory...) -> ControlEvent {
54 | let observables = factories.map { factory in
55 | self.gesture(factory).asObservable() as Observable
56 | }
57 | let source = Observable.from(observables).merge()
58 | return ControlEvent(events: source)
59 | }
60 |
61 | /**
62 | Reactive wrapper for a single view gesture recognizer.
63 | It automatically attaches the gesture recognizer to the receiver view.
64 | The value the `Observable` emits is the gesture recognizer itself.
65 |
66 | rx.gesture can't error and is subscribed/observed on main scheduler.
67 | - parameter factory: a `Factory` you want to use to create the `GestureRecognizer` to add and observe
68 | - returns: a `ControlEvent` that re-emit the gesture recognizer itself
69 | */
70 | public func gesture(_ factory: Factory) -> ControlEvent {
71 | self.gesture(factory.gesture)
72 | }
73 |
74 | /**
75 | Reactive wrapper for a single view gesture recognizer.
76 | It automatically attaches the gesture recognizer to the receiver view.
77 | The value the `Observable` emits is the gesture recognizer itself.
78 |
79 | rx.gesture can't error and is subscribed/observed on main scheduler.
80 | - parameter gesture: a `GestureRecognizer` you want to add and observe
81 | - returns: a `ControlEvent` that re-emit the gesture recognizer itself
82 | */
83 | public func gesture(_ gesture: G) -> ControlEvent {
84 |
85 | let source = Observable.deferred { [weak control = self.base] () -> Observable in
86 | MainScheduler.ensureExecutingOnScheduler()
87 |
88 | guard let control = control else { return .empty() }
89 |
90 | let genericGesture = gesture as RxGestureRecognizer
91 |
92 | #if os(iOS)
93 | control.isUserInteractionEnabled = true
94 | #endif
95 |
96 | control.addGestureRecognizer(gesture)
97 |
98 | return genericGesture.rx.event
99 | .compactMap { $0 as? G }
100 | .startWith(gesture)
101 | .do(onDispose: { [weak control, weak gesture] () in
102 | guard let gesture = gesture else { return }
103 | DispatchQueue.main.async {
104 | control?.removeGestureRecognizer(gesture)
105 | }
106 | })
107 | .take(until: control.rx.deallocated)
108 | }
109 |
110 | return ControlEvent(events: source)
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/ForceTouchGestureRecognizer.swift:
--------------------------------------------------------------------------------
1 | #if canImport(UIKit)
2 |
3 | import UIKit.UIGestureRecognizerSubclass
4 | import RxSwift
5 | import RxCocoa
6 |
7 | public class ForceTouchGestureRecognizer: UIGestureRecognizer {
8 |
9 | private var touch: UITouch?
10 | public var force: CGFloat {
11 | touch?.force ?? 0
12 | }
13 |
14 | public var maximumPossibleForce: CGFloat {
15 | touch?.maximumPossibleForce ?? 0
16 | }
17 |
18 | public var absoluteFractionCompleted: CGFloat {
19 | guard maximumPossibleForce > 0 else {
20 | return 0
21 | }
22 | return force / maximumPossibleForce
23 | }
24 |
25 | public var minimumFractionCompletedRequired: CGFloat = 0
26 | public var maximumFractionCompletedRequired: CGFloat = 1
27 |
28 | public var fractionCompleted: CGFloat {
29 | lerp(
30 | mapMin: minimumFractionCompletedRequired, to: 0,
31 | mapMax: maximumFractionCompletedRequired, to: 1,
32 | value: absoluteFractionCompleted
33 | )
34 | }
35 |
36 | public override func touchesBegan(_ touches: Set, with event: UIEvent) {
37 | super.touchesBegan(touches, with: event)
38 |
39 | guard state == .possible else { return }
40 | guard touch == nil else { return }
41 | guard let first = touches.first(where: { $0.phase == .began }) else { return }
42 | touch = first
43 | state = .began
44 | }
45 |
46 | public override func touchesMoved(_ touches: Set, with event: UIEvent) {
47 | super.touchesMoved(touches, with: event)
48 | guard let touch = touch, touches.contains(touch), touch.phase == .moved else { return }
49 | state = .changed
50 | }
51 |
52 | public override func touchesEnded(_ touches: Set, with event: UIEvent) {
53 | super.touchesEnded(touches, with: event)
54 | guard let touch = touch, touches.contains(touch), touch.phase == .ended else { return }
55 | self.touch = nil
56 | state = .ended
57 | }
58 |
59 | public override func touchesCancelled(_ touches: Set, with event: UIEvent) {
60 | super.touchesCancelled(touches, with: event)
61 | guard let touch = touch, touches.contains(touch), touch.phase == .cancelled else { return }
62 | self.touch = nil
63 | state = .cancelled
64 | }
65 | }
66 |
67 | public typealias ForceTouchConfiguration = Configuration
68 | public typealias ForceTouchControlEvent = ControlEvent
69 | public typealias ForceTouchObservable = Observable
70 |
71 | extension Factory where Gesture == RxGestureRecognizer {
72 |
73 | /**
74 | Returns an `AnyFactory` for `ForceTouchGestureRecognizer`
75 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
76 | */
77 | public static func forceTouch(configuration: ForceTouchConfiguration? = nil) -> AnyFactory {
78 | make(configuration: configuration).abstracted()
79 | }
80 | }
81 |
82 | extension Reactive where Base: RxGestureView {
83 |
84 | /**
85 | Returns an observable `ForceTouchGestureRecognizer` events sequence
86 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
87 | */
88 | public func forceTouchGesture(configuration: ForceTouchConfiguration? = nil) -> ForceTouchControlEvent {
89 | gesture(make(configuration: configuration))
90 | }
91 | }
92 |
93 | extension ObservableType where Element: ForceTouchGestureRecognizer {
94 |
95 | /**
96 | Maps the observable `GestureRecognizer` events sequence to an observable sequence of force values.
97 | */
98 | public func asForce() -> Observable {
99 | self.map { $0.force }
100 | }
101 |
102 | public func when(fractionCompletedExceeds threshold: CGFloat) -> Observable {
103 | let source = asObservable()
104 | return source
105 | .when(.began)
106 | .flatMapLatest { [unowned source] _ in
107 | source
108 | .when(.changed)
109 | .filter {
110 | if threshold == 0 {
111 | return $0.fractionCompleted > threshold
112 | } else {
113 | return $0.fractionCompleted >= threshold
114 | }
115 | }
116 | .take(1)
117 | }
118 | }
119 | }
120 |
121 | private func lerp(_ v0: T, _ v1: T, _ t: T) -> T {
122 | v0 + (v1 - v0) * t
123 | }
124 |
125 | private func lerp(mapMin: T, to min: T, mapMax: T, to max: T, value: T) -> T {
126 | lerp(min, max, (value - mapMin) / (mapMax - mapMin))
127 | }
128 |
129 | #endif
130 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/TouchDownGestureRecognizer.swift:
--------------------------------------------------------------------------------
1 | #if canImport(UIKit)
2 |
3 | import UIKit.UIGestureRecognizerSubclass
4 | import RxSwift
5 | import RxCocoa
6 |
7 | public class TouchDownGestureRecognizer: UIGestureRecognizer {
8 |
9 | public override init(target: Any?, action: Selector?) {
10 | super.init(target: target, action: action)
11 |
12 | trigger
13 | .flatMapFirst { [unowned self] _ -> Observable in
14 | let trigger = Observable.just(())
15 | guard self.state == .possible else {
16 | return trigger
17 | }
18 | return trigger.delay(
19 | .milliseconds(Int(self.minimumTouchDuration * 1000)),
20 | scheduler: MainScheduler.instance
21 | )
22 | }
23 | .subscribe(onNext: { [unowned self] _ in
24 | self.touches = self._touches
25 | })
26 | .disposed(by: triggerDisposeBag)
27 | }
28 |
29 | public var minimumTouchDuration: TimeInterval = 0
30 |
31 | /**
32 | When set to `false`, it allows to bypass the touch ignoring mechanism in order to get absolutely all touch down events.
33 | Defaults to `true`.
34 | - note: See [ignore(_ touch: UITouch, for event: UIEvent)](https://developer.apple.com/documentation/uikit/uigesturerecognizer/1620010-ignore)
35 | */
36 | public var isTouchIgnoringEnabled: Bool = true
37 |
38 | @nonobjc public var touches: Set = [] {
39 | didSet {
40 | if touches.isEmpty {
41 | if state == .possible {
42 | state = .cancelled
43 | } else {
44 | state = .ended
45 | }
46 | } else {
47 | if state == .possible {
48 | state = .began
49 | } else {
50 | state = .changed
51 | }
52 | }
53 | }
54 | }
55 |
56 | public override func touchesBegan(_ touches: Set, with event: UIEvent) {
57 | super.touchesBegan(touches, with: event)
58 | setTouches(from: event)
59 | }
60 |
61 | public override func touchesMoved(_ touches: Set, with event: UIEvent) {
62 | super.touchesMoved(touches, with: event)
63 | setTouches(from: event)
64 | }
65 |
66 | public override func touchesEnded(_ touches: Set, with event: UIEvent) {
67 | super.touchesEnded(touches, with: event)
68 | setTouches(from: event)
69 | }
70 |
71 | public override func touchesCancelled(_ touches: Set, with event: UIEvent) {
72 | super.touchesCancelled(touches, with: event)
73 | setTouches(from: event)
74 | }
75 |
76 | private let triggerDisposeBag = DisposeBag()
77 | private let trigger = PublishSubject()
78 | private var _touches: Set = []
79 | private func setTouches(from event: UIEvent) {
80 | _touches = (event.allTouches ?? []).filter { touch in
81 | [.began, .stationary, .moved].contains(touch.phase)
82 | }
83 | trigger.onNext(())
84 | }
85 |
86 | public override func reset() {
87 | super.reset()
88 | touches = []
89 | }
90 |
91 | public override func ignore(_ touch: UITouch, for event: UIEvent) {
92 | guard isTouchIgnoringEnabled else {
93 | return
94 | }
95 | super.ignore(touch, for: event)
96 | }
97 |
98 | }
99 |
100 | public typealias TouchDownConfiguration = Configuration
101 | public typealias TouchDownControlEvent = ControlEvent
102 | public typealias TouchDownObservable = Observable
103 |
104 | extension Factory where Gesture == RxGestureRecognizer {
105 |
106 | /**
107 | Returns an `AnyFactory` for `TouchDownGestureRecognizer`
108 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
109 | */
110 | public static func touchDown(configuration: TouchDownConfiguration? = nil) -> AnyFactory {
111 | make(configuration: configuration).abstracted()
112 | }
113 | }
114 |
115 | extension Reactive where Base: RxGestureView {
116 |
117 | /**
118 | Returns an observable `TouchDownGestureRecognizer` events sequence
119 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
120 | */
121 | public func touchDownGesture(configuration: TouchDownConfiguration? = nil) -> TouchDownControlEvent {
122 | gesture(make(configuration: configuration))
123 | }
124 | }
125 |
126 | extension ObservableType where Element: TouchDownGestureRecognizer {
127 |
128 | /**
129 | Maps the observable `GestureRecognizer` events sequence to an observable sequence of force values.
130 | */
131 | public func asTouches() -> Observable> {
132 | self.map { $0.touches }
133 | }
134 | }
135 |
136 | #endif
137 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/TransformGestureRecognizers.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #if canImport(UIKit)
22 |
23 | import UIKit
24 | import RxSwift
25 | import RxCocoa
26 |
27 | public struct TransformGestureRecognizers {
28 | public let panGesture: UIPanGestureRecognizer
29 | public let rotationGesture: UIRotationGestureRecognizer
30 | public let pinchGesture: UIPinchGestureRecognizer
31 | }
32 |
33 | public struct TransformVelocity {
34 | let translation: CGPoint
35 | let rotation: CGFloat
36 | let scale: CGFloat
37 | }
38 |
39 | public typealias TransformControlEvent = ControlEvent
40 | public typealias TransformObservable = Observable
41 |
42 | extension Reactive where Base: RxGestureView {
43 | public func transformGestures() -> TransformControlEvent {
44 | let source = Observable.combineLatest(panGesture(), rotationGesture(), pinchGesture()) {
45 | TransformGestureRecognizers(
46 | panGesture: $0,
47 | rotationGesture: $1,
48 | pinchGesture: $2
49 | )
50 | }
51 | return ControlEvent(events: source)
52 | }
53 | }
54 |
55 | extension ObservableType where Element == TransformGestureRecognizers {
56 |
57 | public func when(_ states: RxGestureRecognizerState...) -> Observable {
58 | filter { gestures in
59 | states.contains(gestures.panGesture.state)
60 | || states.contains(gestures.rotationGesture.state)
61 | || states.contains(gestures.pinchGesture.state)
62 | }
63 | }
64 |
65 | public func asTransform(in view: TargetView = .view) -> Observable<(transform: CGAffineTransform, velocity: TransformVelocity)> {
66 | map { gestures in
67 | let translationView = view.targetView(for: gestures.panGesture)
68 | let translation = gestures.panGesture.translation(in: translationView)
69 |
70 | let transform = CGAffineTransform.identity
71 | .rotated(by: gestures.rotationGesture.rotation)
72 | .scaledBy(x: gestures.pinchGesture.scale, y: gestures.pinchGesture.scale)
73 | .translatedBy(x: translation.x, y: translation.y)
74 |
75 | let velocity = TransformVelocity(
76 | translation: gestures.panGesture.velocity(in: translationView),
77 | rotation: gestures.rotationGesture.velocity,
78 | scale: gestures.pinchGesture.velocity
79 | )
80 |
81 | return (transform, velocity)
82 | }
83 | }
84 | }
85 |
86 | #endif
87 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/UIHoverGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #if canImport(UIKit)
22 |
23 | import UIKit
24 | import RxSwift
25 | import RxCocoa
26 |
27 |
28 | @available(iOS 13.0, *)
29 | public typealias HoverConfiguration = Configuration
30 | @available(iOS 13.0, *)
31 | public typealias HoverControlEvent = ControlEvent
32 | @available(iOS 13.0, *)
33 | public typealias HoverObservable = Observable
34 |
35 |
36 | @available(iOS 13.0, *)
37 | extension Factory where Gesture == RxGestureRecognizer {
38 |
39 | /**
40 | Returns an `AnyFactory` for `UIHoverGestureRecognizer`
41 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
42 | */
43 | public static func hover(configuration: HoverConfiguration? = nil) -> AnyFactory {
44 | make(configuration: configuration).abstracted()
45 | }
46 | }
47 |
48 | @available(iOS 13.0, *)
49 | extension Reactive where Base: RxGestureView {
50 |
51 | /**
52 | Returns an observable `UIHoverGestureRecognizer` events sequence
53 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
54 | */
55 | public func hoverGesture(configuration: HoverConfiguration? = nil) -> HoverControlEvent {
56 | gesture(make(configuration: configuration))
57 | }
58 | }
59 |
60 | #endif
61 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/UILongPressGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #if canImport(UIKit)
22 |
23 | import UIKit
24 | import RxSwift
25 | import RxCocoa
26 |
27 | public typealias LongPressConfiguration = Configuration
28 | public typealias LongPressControlEvent = ControlEvent
29 | public typealias LongPressObservable = Observable
30 |
31 | extension Factory where Gesture == RxGestureRecognizer {
32 |
33 | /**
34 | Returns an `AnyFactory` for `UILongPressGestureRecognizer`
35 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
36 | */
37 | public static func longPress(configuration: LongPressConfiguration? = nil) -> AnyFactory {
38 | make(configuration: configuration).abstracted()
39 | }
40 | }
41 |
42 | extension Reactive where Base: RxGestureView {
43 |
44 | /**
45 | Returns an observable `UILongPressGestureRecognizer` events sequence
46 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
47 | */
48 | public func longPressGesture(configuration: LongPressConfiguration? = nil) -> LongPressControlEvent {
49 | gesture(make(configuration: configuration))
50 | }
51 | }
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/UIPanGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #if canImport(UIKit)
22 |
23 | import UIKit
24 | import RxSwift
25 | import RxCocoa
26 |
27 | public typealias PanConfiguration = Configuration
28 | public typealias PanControlEvent = ControlEvent
29 | public typealias PanObservable = Observable
30 |
31 | extension Factory where Gesture == RxGestureRecognizer {
32 |
33 | /**
34 | Returns an `AnyFactory` for `UIPanGestureRecognizer`
35 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
36 | */
37 | public static func pan(configuration: PanConfiguration? = nil) -> AnyFactory {
38 | make(configuration: configuration).abstracted()
39 | }
40 | }
41 |
42 | extension Reactive where Base: RxGestureView {
43 |
44 | /**
45 | Returns an observable `UIPanGestureRecognizer` events sequence
46 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
47 | */
48 | public func panGesture(configuration: PanConfiguration? = nil) -> PanControlEvent {
49 | gesture(make(configuration: configuration))
50 | }
51 | }
52 |
53 | extension ObservableType where Element: UIPanGestureRecognizer {
54 |
55 | /**
56 | Maps the observable `GestureRecognizer` events sequence to an observable sequence of translation values of the pan gesture in the coordinate system of the specified `view` alongside the gesture velocity.
57 |
58 | - parameter view: A `TargetView` value on which the gesture took place.
59 | */
60 | public func asTranslation(in view: TargetView = .view) -> Observable<(translation: CGPoint, velocity: CGPoint)> {
61 | self.map { gesture in
62 | let view = view.targetView(for: gesture)
63 | return (
64 | gesture.translation(in: view),
65 | gesture.velocity(in: view)
66 | )
67 | }
68 | }
69 | }
70 |
71 | #endif
72 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/UIPinchGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #if canImport(UIKit)
22 |
23 | import UIKit
24 | import RxSwift
25 | import RxCocoa
26 |
27 | public typealias PinchConfiguration = Configuration
28 | public typealias PinchControlEvent = ControlEvent
29 | public typealias PinchObservable = Observable
30 |
31 | extension Factory where Gesture == RxGestureRecognizer {
32 |
33 | /**
34 | Returns an `AnyFactory` for `UIPinchGestureRecognizer`
35 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
36 | */
37 | public static func pinch(configuration: PinchConfiguration? = nil) -> AnyFactory {
38 | make(configuration: configuration).abstracted()
39 | }
40 | }
41 |
42 | extension Reactive where Base: RxGestureView {
43 |
44 | /**
45 | Returns an observable `UIPinchGestureRecognizer` events sequence
46 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
47 | */
48 | public func pinchGesture(configuration: PinchConfiguration? = nil) -> PinchControlEvent {
49 | gesture(make(configuration: configuration))
50 | }
51 | }
52 |
53 | extension ObservableType where Element: UIPinchGestureRecognizer {
54 |
55 | /**
56 | Maps the observable `GestureRecognizer` events sequence to an observable sequence of scale factors relative to the points of the two touches in screen coordinates alongside the gesture velocity.
57 | */
58 | public func asScale() -> Observable<(scale: CGFloat, velocity: CGFloat)> {
59 | self.map { gesture in
60 | (gesture.scale, gesture.velocity)
61 | }
62 | }
63 | }
64 |
65 | #endif
66 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/UIRotationGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #if canImport(UIKit)
22 |
23 | import UIKit
24 | import RxSwift
25 | import RxCocoa
26 |
27 | public typealias RotationConfiguration = Configuration
28 | public typealias RotationControlEvent = ControlEvent
29 | public typealias RotationObservable = Observable
30 |
31 | extension Factory where Gesture == RxGestureRecognizer {
32 |
33 | /**
34 | Returns an `AnyFactory` for `UIRotationGestureRecognizer`
35 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
36 | */
37 | public static func rotation(configuration: RotationConfiguration? = nil) -> AnyFactory {
38 | make(configuration: configuration).abstracted()
39 | }
40 | }
41 |
42 | extension Reactive where Base: RxGestureView {
43 |
44 | /**
45 | Returns an observable `UIRotationGestureRecognizer` events sequence
46 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
47 | */
48 | public func rotationGesture(configuration: RotationConfiguration? = nil) -> RotationControlEvent {
49 | gesture(make(configuration: configuration))
50 | }
51 | }
52 |
53 | extension ObservableType where Element: UIRotationGestureRecognizer {
54 |
55 | /**
56 | Maps the observable `GestureRecognizer` events sequence to an observable sequence of rotation values of the gesture in radians alongside the gesture velocity.
57 | */
58 | public func asRotation() -> Observable<(rotation: CGFloat, velocity: CGFloat)> {
59 | self.map { gesture in
60 | (gesture.rotation, gesture.velocity)
61 | }
62 | }
63 | }
64 |
65 | #endif
66 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/UIScreenEdgePanGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #if canImport(UIKit)
22 |
23 | import UIKit
24 | import RxSwift
25 | import RxCocoa
26 |
27 | public typealias ScreenEdgePanConfiguration = Configuration
28 | public typealias ScreenEdgePanControlEvent = ControlEvent
29 | public typealias ScreenEdgePanObservable = Observable
30 |
31 | extension Factory where Gesture == RxGestureRecognizer {
32 |
33 | /**
34 | Returns an `AnyFactory` for `UIScreenEdgePanGestureRecognizer`
35 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
36 | */
37 | public static func screenEdgePan(configuration: ScreenEdgePanConfiguration? = nil) -> AnyFactory {
38 | make(configuration: configuration).abstracted()
39 | }
40 | }
41 |
42 | extension Reactive where Base: RxGestureView {
43 |
44 | /**
45 | Returns an observable `UIScreenEdgePanGestureRecognizer` events sequence
46 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
47 | */
48 | public func screenEdgePanGesture(configuration: ScreenEdgePanConfiguration? = nil) -> ScreenEdgePanControlEvent {
49 | gesture(make(configuration: configuration))
50 | }
51 | }
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/UISwipeGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #if canImport(UIKit)
22 |
23 | import UIKit
24 | import RxSwift
25 | import RxCocoa
26 |
27 | public enum SwipeDirection {
28 | case right, left, up, down
29 |
30 | fileprivate typealias SwipeGestureRecognizerDirection = UISwipeGestureRecognizer.Direction
31 |
32 | fileprivate var direction: SwipeGestureRecognizerDirection {
33 | switch self {
34 | case .right: return .right
35 | case .left: return .left
36 | case .up: return .up
37 | case .down: return .down
38 | }
39 | }
40 | }
41 |
42 | private func make(direction: SwipeDirection, configuration: Configuration?) -> Factory {
43 | make {
44 | $0.direction = direction.direction
45 | configuration?($0, $1)
46 | }
47 | }
48 |
49 | public typealias SwipeConfiguration = Configuration
50 | public typealias SwipeControlEvent = ControlEvent
51 | public typealias SwipeObservable = Observable
52 |
53 | extension Factory where Gesture == RxGestureRecognizer {
54 |
55 | /**
56 | Returns an `AnyFactory` for `UISwipeGestureRecognizer`
57 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
58 | */
59 | public static func swipe(direction: SwipeDirection, configuration: SwipeConfiguration? = nil) -> AnyFactory {
60 | make(direction: direction, configuration: configuration).abstracted()
61 | }
62 | }
63 |
64 | extension Reactive where Base: RxGestureView {
65 |
66 | /**
67 | Returns an observable `UISwipeGestureRecognizer` events sequence
68 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
69 | */
70 | private func swipeGesture(direction: SwipeDirection,configuration: SwipeConfiguration? = nil) -> SwipeControlEvent {
71 | gesture(make(direction: direction, configuration: configuration))
72 | }
73 |
74 | /**
75 | Returns an observable `UISwipeGestureRecognizer` events sequence
76 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
77 | */
78 | public func swipeGesture(_ directions: Set,configuration: SwipeConfiguration? = nil) -> SwipeControlEvent {
79 | let source = Observable.merge(directions.map {
80 | swipeGesture(direction: $0, configuration: configuration).asObservable()
81 | })
82 | return ControlEvent(events: source)
83 | }
84 |
85 | /**
86 | Returns an observable `UISwipeGestureRecognizer` events sequence
87 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
88 | */
89 | public func swipeGesture(_ directions: SwipeDirection...,configuration: SwipeConfiguration? = nil) -> SwipeControlEvent {
90 | swipeGesture(Set(directions), configuration: configuration)
91 | }
92 |
93 | }
94 |
95 | #endif
96 |
--------------------------------------------------------------------------------
/Pod/Classes/iOS/UITapGestureRecognizer+RxGesture.swift:
--------------------------------------------------------------------------------
1 | // Copyright (c) RxSwiftCommunity
2 |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in
11 | // all copies or substantial portions of the Software.
12 |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | // THE SOFTWARE.
20 |
21 | #if canImport(UIKit)
22 |
23 | import UIKit
24 | import RxSwift
25 | import RxCocoa
26 |
27 | public typealias TapConfiguration = Configuration
28 | public typealias TapControlEvent = ControlEvent
29 | public typealias TapObservable = Observable
30 |
31 | extension Factory where Gesture == RxGestureRecognizer {
32 |
33 | /**
34 | Returns an `AnyFactory` for `UITapGestureRecognizer`
35 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
36 | */
37 | public static func tap(configuration: TapConfiguration? = nil) -> AnyFactory {
38 | make(configuration: configuration).abstracted()
39 | }
40 | }
41 |
42 | extension Reactive where Base: RxGestureView {
43 |
44 | /**
45 | Returns an observable `UITapGestureRecognizer` events sequence
46 | - parameter configuration: A closure that allows to fully configure the gesture recognizer
47 | */
48 | public func tapGesture(configuration: TapConfiguration? = nil) -> TapControlEvent {
49 | gesture(make(configuration: configuration))
50 | }
51 | }
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RxGesture
2 |
3 | [](http://cocoapods.org/pods/RxGesture)
4 | [](http://cocoapods.org/pods/RxGesture)
5 | [](http://cocoapods.org/pods/RxGesture)
6 |
7 | ## Usage
8 |
9 | 
10 |
11 | To run the example project, clone the repo, in the __Example__ folder open `RxGesture.xcworkspace`.
12 |
13 | You _might_ need to run `pod install` from the Example directory first.
14 |
15 | ---
16 |
17 | __RxGesture__ allows you to easily turn any view into a tappable or swipeable control like so:
18 |
19 | ```swift
20 | view.rx
21 | .tapGesture()
22 | .when(.recognized)
23 | .subscribe(onNext: { _ in
24 | //react to taps
25 | })
26 | .disposed(by: stepBag)
27 | ```
28 |
29 | You can also react to more than one gesture. For example to dismiss a photo preview you might want to do that when the user taps it, or swipes up or down:
30 |
31 | ```swift
32 | view.rx
33 | .anyGesture(.tap(), .swipe([.up, .down]))
34 | .when(.recognized)
35 | .subscribe(onNext: { _ in
36 | //dismiss presented photo
37 | })
38 | .disposed(by: stepBag)
39 | ```
40 |
41 | `rx.gesture` is defined as `Observable` where `G` is the actual type of the gesture recognizer so what it emits is the gesture recognizer itself (handy if want to call methods like `asLocation(in view:)` or `asTranslation(in view:)`)
42 |
43 |
44 | #### On iOS, RxGesture supports:
45 |
46 | ```swift
47 | view.rx.tapGesture() -> ControlEvent
48 | view.rx.pinchGesture() -> ControlEvent
49 | view.rx.swipeGesture(.left) -> ControlEvent
50 | view.rx.panGesture() -> ControlEvent
51 | view.rx.longPressGesture() -> ControlEvent
52 | view.rx.rotationGesture() -> ControlEvent
53 | view.rx.screenEdgePanGesture() -> ControlEvent
54 | view.rx.hoverGesture() -> ControlEvent
55 |
56 | view.rx.anyGesture(.tap(), ...) -> ControlEvent
57 | view.rx.anyGesture(.pinch(), ...) -> ControlEvent
58 | view.rx.anyGesture(.swipe(.left), ...) -> ControlEvent
59 | view.rx.anyGesture(.pan(), ...) -> ControlEvent
60 | view.rx.anyGesture(.longPress(), ...) -> ControlEvent
61 | view.rx.anyGesture(.rotation(), ...) -> ControlEvent
62 | view.rx.anyGesture(.screenEdgePan(), ...) -> ControlEvent
63 | view.rx.anyGesture(.hover(), ...) -> ControlEvent
64 | ```
65 |
66 | #### On macOS, RxGesture supports:
67 |
68 | ```swift
69 | view.rx.clickGesture() -> ControlEvent
70 | view.rx.rightClickGesture() -> ControlEvent
71 | view.rx.panGesture() -> ControlEvent
72 | view.rx.pressGesture() -> ControlEvent
73 | view.rx.rotationGesture() -> ControlEvent
74 | view.rx.magnificationGesture() -> ControlEvent
75 |
76 | view.rx.anyGesture(.click(), ...) -> ControlEvent
77 | view.rx.anyGesture(.rightClick(), ...) -> ControlEvent
78 | view.rx.anyGesture(.pan(), ...) -> ControlEvent
79 | view.rx.anyGesture(.press(), ...) -> ControlEvent
80 | view.rx.anyGesture(.rotation(), ...) -> ControlEvent
81 | view.rx.anyGesture(.magnification(), ...) -> ControlEvent
82 | ```
83 |
84 |
85 | ℹ️ If you use a gesture recognizer alone, prefer the `view.rx.fooGesture()` syntax over `view.rx.anyGesture(.foo())` because it returns the concrete `UIGestureRecognizer` subclass and avoid you to cast it in `subscribe()`.
86 |
87 |
88 | ## Filtering State
89 |
90 | By default, there is no filter on the state of the gesture recognizer. That means that you will always receive a first event with the initial state of the gesture recognizer (almost always `.possible`).
91 |
92 | Here are the preferred states that can be used for each kind of gestures (__iOS__ and __macOS__):
93 |
94 | Kind | States
95 | ---|---
96 | `.tap()` `.click()` `.rightClick()` `.swipe()`| `.recognized`
97 | `.longPress()` `.press()` | `.began`
98 | `.pan()` `.pinch()` `.rotation()` `.magnification()` `.screenEdgePan()` | `.began` `.changed` `.ended`
99 |
100 | You usually filter the state using the `.when()` operator:
101 | ```swift
102 | view.rx.tapGesture().when(.recognized)
103 | view.rx.panGesture().when(.began, .changed, .ended)
104 | ```
105 |
106 | If you are observing multiple gestures at once, you can use the `.when()` operator if you want to filter against the same state for __all__ gesture recognizers, or use the tuple syntax for individual filtering:
107 |
108 | ```swift
109 | view.rx
110 | .anyGesture(.tap(), .swipe([.up, .down]))
111 | .when(.recognized)
112 | .subscribe(onNext: { gesture in
113 | // Called whenever a tap, a swipe-up or a swipe-down is recognized (state == .recognized)
114 | })
115 | .disposed(by: bag)
116 |
117 | view.rx
118 | .anyGesture(
119 | (.tap(), when: .recognized),
120 | (.pan(), when: .ended)
121 | )
122 | .subscribe(onNext: { gesture in
123 | // Called whenever:
124 | // - a tap is recognized (state == .recognized)
125 | // - or a pan is ended (state == .ended)
126 | })
127 | .disposed(by: bag)
128 | ```
129 |
130 |
131 | __The demo app includes examples for all recognizers ➡️ [iOS](Example/RxGesture/ViewController.swift), [macOS](Example/RxGesture-OSX/ViewController.swift)__.
132 |
133 | ## Delegate customization
134 | ### Lightweight customization
135 | Each gesture recognizer has a default `RxGestureRecognizerDelegate`. It allows you to customize every delegate method using a policy:
136 | - `.always` will return `true` to the corresponding delegate method
137 | - `.never` will return `false` to the corresponding delegate method
138 | - `.custom` takes an associated closure that will be executed to return a value to the corresponding delegate method
139 |
140 | Here are the available policies with their corresponding delegate method:
141 | ```swift
142 | beginPolicy -> gestureRecognizerShouldBegin(:_)
143 | touchReceptionPolicy -> gestureRecognizer(_:shouldReceive:)
144 | selfFailureRequirementPolicy -> gestureRecognizer(_:shouldBeRequiredToFailBy:)
145 | otherFailureRequirementPolicy -> gestureRecognizer(_:shouldRequireFailureOf:)
146 | simultaneousRecognitionPolicy -> gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)
147 | eventRecognitionAttemptPolicy -> gestureRecognizer(_:shouldAttemptToRecognizeWith:) // macOS only
148 | pressReceptionPolicy -> gestureRecognizer(_:shouldReceive:) // iOS only
149 | ```
150 |
151 | This delegate can be customized in the configuration closure:
152 | ```swift
153 | view.rx.tapGesture(configuration: { gestureRecognizer, delegate in
154 | delegate.simultaneousRecognitionPolicy = .always // (default value)
155 | // or
156 | delegate.simultaneousRecognitionPolicy = .never
157 | // or
158 | delegate.simultaneousRecognitionPolicy = .custom { gestureRecognizer, otherGestureRecognizer in
159 | return otherGestureRecognizer is UIPanGestureRecognizer
160 | }
161 | delegate.otherFailureRequirementPolicy = .custom { gestureRecognizer, otherGestureRecognizer in
162 | return otherGestureRecognizer is UILongPressGestureRecognizer
163 | }
164 | })
165 | ```
166 |
167 | Default values can be found in [`RxGestureRecognizerDelegate.swift`](Pod/Classes/RxGestureRecognizerDelegate.swift#L56).
168 |
169 | ### Full customization
170 | You can also replace the default delegate by your own, or remove it.
171 | ```swift
172 | view.rx.tapGesture { [unowned self] gestureRecognizer, delegate in
173 | gestureRecognizer.delegate = nil
174 | // or
175 | gestureRecognizer.delegate = self
176 | }
177 | ```
178 |
179 | ## Requirements
180 |
181 | This library depends on both __RxSwift__ and __RxCocoa__.
182 |
183 |
184 | ## Installation
185 |
186 | ### [CocoaPods](https://guides.cocoapods.org/using/using-cocoapods.html)
187 |
188 | Add this to `Podfile`
189 |
190 | ```swift
191 | pod "RxGesture"
192 | ```
193 |
194 | ```bash
195 | $ pod install
196 | ```
197 |
198 | ### [Carthage](https://github.com/Carthage/Carthage)
199 |
200 | Add this to `Cartfile`
201 |
202 | ```
203 | github "RxSwiftCommunity/RxGesture" ~> 3.0
204 | ```
205 |
206 | ```bash
207 | $ carthage update
208 | ```
209 |
210 | ## Thanks
211 |
212 | Everyone in the RxSwift Slack channel 💯
213 |
214 | ## License
215 |
216 | RxGesture is available under the MIT license. See the LICENSE file for more info.
217 |
--------------------------------------------------------------------------------
/RxGesture.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod lib lint RxGesture.podspec' to ensure this is a
3 | # valid spec before submitting.
4 | #
5 |
6 | Pod::Spec.new do |s|
7 | s.name = "RxGesture"
8 | s.version = "4.0.4"
9 | s.summary = "RxSwift reactive wrapper for view gestures."
10 | s.swift_version = "5.1"
11 |
12 | s.description = <<-DESC
13 | RxSwift reactive wrapper for view gestures. It lets you to easily observe
14 | a single gesture like tap or a custom group of gestures on a view. You can
15 | combine taps, presses, or swipes in any direction
16 | DESC
17 |
18 | s.homepage = "https://github.com/RxSwiftCommunity/RxGesture"
19 | s.license = 'MIT'
20 | s.authors = { "RxSwiftCommunity" => "https://github.com/RxSwiftCommunity", "Jérôme Alves" => "j.alves@me.com" }
21 | s.source = { :git => "https://github.com/RxSwiftCommunity/RxGesture.git", :tag => s.version.to_s }
22 |
23 | s.requires_arc = true
24 |
25 | s.ios.deployment_target = '9.0'
26 | s.osx.deployment_target = '10.10'
27 |
28 | s.source_files = 'Pod/Classes/*.swift'
29 |
30 | s.ios.source_files = 'Pod/Classes/iOS/*.swift'
31 | s.osx.source_files = 'Pod/Classes/OSX/*.swift'
32 |
33 | s.dependency 'RxSwift', '~> 6.0'
34 | s.dependency 'RxCocoa', '~> 6.0'
35 |
36 | end
37 |
--------------------------------------------------------------------------------
/RxGesture/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | opt_in_rules:
2 | - overridden_super_call
3 | - private_outlet
4 | - prohibited_super_call
5 | - first_where
6 | - closure_spacing
7 | - unneeded_parentheses_in_closure_argument
8 | - redundant_nil_coalescing
9 | - pattern_matching_keywords
10 | - explicit_init
11 | - contains_over_first_not_nil
12 | - implicit_return
13 |
14 | disabled_rules:
15 | - line_length
16 | - trailing_whitespace
17 | - type_name
18 | - identifier_name
19 | - vertical_whitespace
20 | - trailing_newline
21 | - opening_brace
22 | - large_tuple
23 | - file_length
24 | - comma
25 | - colon
26 | - private_over_fileprivate
27 | - force_cast
28 | - force_try
29 | - function_parameter_count
30 | - statement_position
31 | - legacy_hashing
32 | - todo
33 | - operator_whitespace
34 | - type_body_length
35 | - function_body_length
36 | - cyclomatic_complexity
37 |
38 | included:
39 | - ../Pod/Classes
--------------------------------------------------------------------------------
/RxGesture/RxGesture copy-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 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/RxGesture/RxGesture-iOS-Tests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/RxGesture/RxGesture-iOS-Tests/RxGestureTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Utilities.swift
3 | // RxGesture-iOS-Tests
4 | //
5 | // Created by Jérôme Alves on 05/11/2017.
6 | // Copyright © 2017 RxSwiftCommunity. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import XCTest
11 | import RxSwift
12 | import RxCocoa
13 | import RxTest
14 | import RxBlocking
15 | @testable import RxGesture
16 |
17 | class RxGestureTests: XCTestCase {
18 |
19 | var disposeBag: DisposeBag!
20 | var view: UIView!
21 | var gesture: UIGestureRecognizer!
22 |
23 | override func setUp() {
24 | super.setUp()
25 | disposeBag = DisposeBag()
26 | view = UIView()
27 | gesture = UIGestureRecognizer()
28 | }
29 |
30 | override func tearDown() {
31 | super.tearDown()
32 | disposeBag = nil
33 | view = nil
34 | gesture = nil
35 | }
36 |
37 | func testObservable() {
38 |
39 | let states: [UIGestureRecognizer.State] = [.began, .changed, .changed, .changed, .ended]
40 |
41 | send(states)
42 |
43 | let expected = [.possible] + states
44 |
45 | let result = try? view.rx.gesture(gesture)
46 | .map { $0.state }
47 | .take(expected.count)
48 | .toBlocking(timeout: 1)
49 | .toArray()
50 |
51 | XCTAssertEqual(result ?? [], expected)
52 | }
53 |
54 | func send(_ states: [UIGestureRecognizer.State]) {
55 | guard let first = states.first else {
56 | return
57 | }
58 | DispatchQueue.main.async {
59 | self.gesture.state = first
60 | self.send(Array(states[1...]))
61 | }
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/RxGesture/RxGesture.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/RxGesture/RxGesture.xcodeproj/xcshareddata/xcschemes/RxGesture-OSX.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/RxGesture/RxGesture.xcodeproj/xcshareddata/xcschemes/RxGesture-iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
78 |
79 |
85 |
86 |
87 |
88 |
89 |
90 |
96 |
97 |
103 |
104 |
105 |
106 |
108 |
109 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/RxGesture/RxGesture/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 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/RxGesture/RxGesture/RxGesture.h:
--------------------------------------------------------------------------------
1 | //
2 | // RxGesture.h
3 | // RxGesture
4 | //
5 | // Created by James Perlman on 11/27/16.
6 | // Copyright © 2016 AutoLotto. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for RxGesture.
12 | FOUNDATION_EXPORT double RxGestureVersionNumber;
13 |
14 | //! Project version string for RxGesture.
15 | FOUNDATION_EXPORT const unsigned char RxGestureVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | if ! command -v carthage > /dev/null; then
4 | printf 'Carthage is not installed.\n'
5 | printf 'See https://github.com/Carthage/Carthage for install instructions.\n'
6 | exit 1
7 | fi
8 |
9 | carthage update --use-xcframeworks --use-submodules --no-use-binaries
10 |
--------------------------------------------------------------------------------