Coder Social home page Coder Social logo

rxgesture's Introduction

RxGesture

Version License Platform

Usage

To run the example project, clone the repo, in the Example folder open RxGesture.xcworkspace.

You might need to run pod install from the Example directory first.


RxGesture allows you to easily turn any view into a tappable or swipeable control like so:

view.rx
  .tapGesture()
  .when(.recognized)
  .subscribe(onNext: { _ in
    //react to taps
  })
  .disposed(by: stepBag)

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:

view.rx
  .anyGesture(.tap(), .swipe([.up, .down]))
  .when(.recognized)
  .subscribe(onNext: { _ in
    //dismiss presented photo
  })
  .disposed(by: stepBag)

rx.gesture is defined as Observable<G> 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:))

On iOS, RxGesture supports:

view.rx.tapGesture()           -> ControlEvent<UITapGestureRecognizer>
view.rx.pinchGesture()         -> ControlEvent<UIPinchGestureRecognizer>
view.rx.swipeGesture(.left)    -> ControlEvent<UISwipeGestureRecognizer>
view.rx.panGesture()           -> ControlEvent<UIPanGestureRecognizer>
view.rx.longPressGesture()     -> ControlEvent<UILongPressGestureRecognizer>
view.rx.rotationGesture()      -> ControlEvent<UIRotationGestureRecognizer>
view.rx.screenEdgePanGesture() -> ControlEvent<UIScreenEdgePanGestureRecognizer>
view.rx.hoverGesture()         -> ControlEvent<UIHoverGestureRecognizer>

view.rx.anyGesture(.tap(), ...)           -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.pinch(), ...)         -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.swipe(.left), ...)    -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.pan(), ...)           -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.longPress(), ...)     -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.rotation(), ...)      -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.screenEdgePan(), ...) -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.hover(), ...)         -> ControlEvent<UIGestureRecognizer>

On macOS, RxGesture supports:

view.rx.clickGesture()         -> ControlEvent<NSClickGestureRecognizer>
view.rx.rightClickGesture()    -> ControlEvent<NSClickGestureRecognizer>
view.rx.panGesture()           -> ControlEvent<NSPanGestureRecognizer>
view.rx.pressGesture()         -> ControlEvent<NSPressGestureRecognizer>
view.rx.rotationGesture()      -> ControlEvent<NSRotationGestureRecognizer>
view.rx.magnificationGesture() -> ControlEvent<NSMagnificationGestureRecognizer>

view.rx.anyGesture(.click(), ...)         -> ControlEvent<NSGestureRecognizer>
view.rx.anyGesture(.rightClick(), ...)    -> ControlEvent<NSGestureRecognizer>
view.rx.anyGesture(.pan(), ...)           -> ControlEvent<NSGestureRecognizer>
view.rx.anyGesture(.press(), ...)         -> ControlEvent<NSGestureRecognizer>
view.rx.anyGesture(.rotation(), ...)      -> ControlEvent<NSGestureRecognizer>
view.rx.anyGesture(.magnification(), ...) -> ControlEvent<NSGestureRecognizer>

ℹ️ 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().

Filtering State

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).

Here are the preferred states that can be used for each kind of gestures (iOS and macOS):

Kind States
.tap() .click() .rightClick() .swipe() .recognized
.longPress() .press() .began
.pan() .pinch() .rotation() .magnification() .screenEdgePan() .began .changed .ended

You usually filter the state using the .when() operator:

view.rx.tapGesture().when(.recognized)
view.rx.panGesture().when(.began, .changed, .ended)

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:

view.rx
  .anyGesture(.tap(), .swipe([.up, .down]))
  .when(.recognized)
  .subscribe(onNext: { gesture in
    // Called whenever a tap, a swipe-up or a swipe-down is recognized (state == .recognized)
  })
  .disposed(by: bag)

view.rx
  .anyGesture(
    (.tap(), when: .recognized),
    (.pan(), when: .ended)
  )
  .subscribe(onNext: { gesture in
    // Called whenever:
    // - a tap is recognized (state == .recognized)
    // - or a pan is ended (state == .ended)
  })
  .disposed(by: bag)

The demo app includes examples for all recognizers ➡️ iOS, macOS.

Delegate customization

Lightweight customization

Each gesture recognizer has a default RxGestureRecognizerDelegate. It allows you to customize every delegate method using a policy:

  • .always will return true to the corresponding delegate method
  • .never will return false to the corresponding delegate method
  • .custom takes an associated closure that will be executed to return a value to the corresponding delegate method

Here are the available policies with their corresponding delegate method:

beginPolicy                   -> gestureRecognizerShouldBegin(:_)
touchReceptionPolicy          -> gestureRecognizer(_:shouldReceive:)
selfFailureRequirementPolicy  -> gestureRecognizer(_:shouldBeRequiredToFailBy:)
otherFailureRequirementPolicy -> gestureRecognizer(_:shouldRequireFailureOf:)
simultaneousRecognitionPolicy -> gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)
eventRecognitionAttemptPolicy -> gestureRecognizer(_:shouldAttemptToRecognizeWith:) // macOS only
pressReceptionPolicy          -> gestureRecognizer(_:shouldReceive:) // iOS only

This delegate can be customized in the configuration closure:

view.rx.tapGesture(configuration: { gestureRecognizer, delegate in
  delegate.simultaneousRecognitionPolicy = .always // (default value)
  // or
  delegate.simultaneousRecognitionPolicy = .never
  // or
  delegate.simultaneousRecognitionPolicy = .custom { gestureRecognizer, otherGestureRecognizer in
    return otherGestureRecognizer is UIPanGestureRecognizer
  }
  delegate.otherFailureRequirementPolicy = .custom { gestureRecognizer, otherGestureRecognizer in
    return otherGestureRecognizer is UILongPressGestureRecognizer
  }
})

Default values can be found in RxGestureRecognizerDelegate.swift.

Full customization

You can also replace the default delegate by your own, or remove it.

view.rx.tapGesture { [unowned self] gestureRecognizer, delegate in
  gestureRecognizer.delegate = nil
  // or
  gestureRecognizer.delegate = self
}

Requirements

This library depends on both RxSwift and RxCocoa.

Installation

Add this to Podfile

pod "RxGesture"
$ pod install

Add this to Cartfile

github "RxSwiftCommunity/RxGesture" ~> 3.0
$ carthage update

Thanks

Everyone in the RxSwift Slack channel 💯

License

RxGesture is available under the MIT license. See the LICENSE file for more info.

rxgesture's People

Contributors

arangato avatar catelina777 avatar chipp avatar clementleroy avatar dependabot[bot] avatar devxoul avatar endore8 avatar fpillet avatar freak4pc avatar glaurent avatar icanzilb avatar idonjose avatar jamesperlman avatar jeehut avatar jegnux avatar katoemba avatar krezzoid avatar lm2343635 avatar loupehope avatar m0rtymerr avatar mgurreta avatar mlight3 avatar mrs- avatar rengate avatar rynecheow avatar shonorio avatar sidmani avatar svyatoslav-zubrin avatar wanbok avatar waterskier2007 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rxgesture's Issues

Make tapGesture more simple

extension Reactive where Base: UIView { var tap: ControlEvent<Void> { return ControlEvent(events: self.tapGesture().when(.recognized).map { _ -> Void in return }) } }

Xcode 11 and Carthage: exit code 65 (compile error: use of undeclared type 'Element')

I'm trying to update everything to Xcode 11/Swift 5.1 and I'm finding this error on Carthage:

*** Building scheme "RxBlocking" in Rx.xcworkspace
*** Building scheme "RxRelay" in Rx.xcworkspace
*** Building scheme "RxSwift" in Rx.xcworkspace
*** Building scheme "RxCocoa" in Rx.xcworkspace
*** Building scheme "RxTest" in Rx.xcworkspace
*** Building scheme "RxDataSources" in RxDataSources.xcodeproj
*** Building scheme "Differentiator" in RxDataSources.xcodeproj
*** Building scheme "RxBlocking-iOS" in Rx.xcworkspace
*** Building scheme "RxCocoa-iOS" in Rx.xcworkspace
*** Building scheme "RxSwift-iOS" in Rx.xcworkspace
*** Building scheme "RxTests-iOS" in Rx.xcworkspace
*** Building scheme "RxGesture-iOS" in RxGesture.xcodeproj
Build Failed
	Task failed with exit code 65:

These are the last lines of the compiling log:

/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/UIPanGestureRecognizer+RxGesture.swift:51:32: error: use of undeclared type 'Element'
extension ObservableType where Element: UIPanGestureRecognizer {
                               ^~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/UIPanGestureRecognizer+RxGesture.swift:60:45: error: cannot convert value of type 'Self.E' to expected argument type 'GestureRecognizer' (aka 'UIGestureRecognizer')
            let view = view.targetView(for: gesture)
                                            ^~~~~~~
                                                    as! GestureRecognizer
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/TouchDownGestureRecognizer.swift:82:32: error: use of undeclared type 'Element'
extension ObservableType where Element: TouchDownGestureRecognizer {
                               ^~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/TouchDownGestureRecognizer.swift:88:30: error: value of type 'Self.E' has no member 'touches'
        return self.map { $0.touches }
                          ~~ ^~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/ForceTouchGestureRecognizer.swift:85:32: error: use of undeclared type 'Element'
extension ObservableType where Element: ForceTouchGestureRecognizer {
                               ^~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/ForceTouchGestureRecognizer.swift:91:30: error: value of type 'Self.E' has no member 'force'
        return self.map { $0.force }
                          ~~ ^~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/TransformGestureRecognizers.swift:58:32: error: use of undeclared type 'Element'
extension ObservableType where Element == TransformGestureRecognizers {
                               ^~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/TransformGestureRecognizers.swift:60:73: error: use of undeclared type 'Element'
    public func when(_ states: GestureRecognizerState...) -> Observable<Element> {
                                                                        ^~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/GestureRecognizer+RxGesture.swift:24:32: error: use of undeclared type 'Element'
extension ObservableType where Element: GestureRecognizer {
                               ^~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/GestureRecognizer+RxGesture.swift:32:73: error: use of undeclared type 'Element'
    public func when(_ states: GestureRecognizerState...) -> Observable<Element> {
                                                                        ^~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/GestureRecognizer+RxGesture.swift:44:74: error: use of undeclared type 'Element'
    internal func when(_ states: [GestureRecognizerState]) -> Observable<Element> {
                                                                         ^~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/View+RxGesture.swift:36:43: error: closure tuple parameter '(AnyFactory, when: GestureRecognizerState)' (aka '(Factory<UIGestureRecognizer>, when: UIGestureRecognizer.State)') does not support destructuring
        let observables = factories.map { gesture, state in
                                          ^~~~~~~~~~~~~~
                                          (arg) -> <#Result#>
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/TransformGestureRecognizers.swift:70:65: error: value of type 'Self.E' has no member 'panGesture'
            let translationView = view.targetView(for: gestures.panGesture)
                                                       ~~~~~~~~ ^~~~~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/GestureRecognizer+RxGesture.swift:57:28: error: value of type 'Self.E' has no member 'location'
            return gesture.location(in: view.targetView(for: gesture))
                   ~~~~~~~ ^~~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/UIPinchGestureRecognizer+RxGesture.swift:51:32: error: use of undeclared type 'Element'
extension ObservableType where Element: UIPinchGestureRecognizer {
                               ^~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/UIPinchGestureRecognizer+RxGesture.swift:58:29: error: value of type 'Self.E' has no member 'scale'
            return (gesture.scale, gesture.velocity)
                    ~~~~~~~ ^~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/UIPinchGestureRecognizer+RxGesture.swift:58:44: error: value of type 'Self.E' has no member 'velocity'
            return (gesture.scale, gesture.velocity)
                                   ~~~~~~~ ^~~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/UIRotationGestureRecognizer+RxGesture.swift:51:32: error: use of undeclared type 'Element'
extension ObservableType where Element: UIRotationGestureRecognizer {
                               ^~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/UIRotationGestureRecognizer+RxGesture.swift:58:29: error: value of type 'Self.E' has no member 'rotation'
            return (gesture.rotation, gesture.velocity)
                    ~~~~~~~ ^~~~~~~~
/Users/fieldmargin/Xcode/notes-ios/Carthage/Checkouts/RxGesture/Pod/Classes/iOS/UIRotationGestureRecognizer+RxGesture.swift:58:47: error: value of type 'Self.E' has no member 'velocity'
            return (gesture.rotation, gesture.velocity)
                                      ~~~~~~~ ^~~~~~~~

I'm using "master" and the resolved file points to the last commit bd13354

Swift on the console:
Welcome to Apple Swift version 5.1 (swiftlang-1100.0.270.13 clang-1100.0.33.7).

xcodebuild -version

Xcode 11.0
Build version 11A420a

Cartfile.resolved:

github "ReactiveX/RxSwift" "5.0.1"
github "RxSwiftCommunity/RxDataSources" "4.0.1"
github "RxSwiftCommunity/RxGesture" "bd13354b45507bb30e4f6ac7142b03cd60a0b244"
github "RxSwiftCommunity/RxOptional" "4.0.0"
github "RxSwiftCommunity/RxRealm" "bac74bdc0c04f5ef1c68d46021a115b536903366"
github "RxSwiftCommunity/RxSwiftExt" "5.1.1"

Any ideas on how to solve this would be appreciated!! Thanks!

RxGesture on containing view + UICollection's didSelect

Hello, I hope it is ok to ask a question here.

I have a collectionView with multiple types of cells.
One type is cells containing a TextView
Another type is cells with just a label.

I want to handle taps on the label cells by implementing the collectionView's didSelectItemAtIndexPath method.

I also want to dismiss the keyboard when there's a tap outside the textView with the following:

self.view.rx.tapGesture().when(.recognized)
  .subscribe(onNext: { [weak self] _ in self?.view.endEditing(true })
  .disposed(by: disposeBag)

When I do this, however, the collectionView's didSelect method is not called anymore.

How do I set RxGesture to handle taps on the view and still pass on the tap event to whichever object might want to handle it down the chain ?

Swift 4 support

Just wondering if there are any plans for Swift 4/Xcode 9 support. The library currently doesn't compile under Swift 4, but I can fix it and create a pull request if someone with write access makes a swift-4 branch for me to compare against.

Swift 4.2 release

Hey @jegnux - Seems like the master branch has Swift 4.2 properly fixed, but a release wasn't cut yet :)

I could do it myself but preferred leaving it to you :]

Let me know if I can help!

RxSwift/RxCocoa 4.5 compatibility

The dependencies in the podspec prevent it from being compatible with the latest versions of RxSwift and RxCoccoa:

s.dependency 'RxSwift', '~> 4.4.0'
s.dependency 'RxCocoa', '~> 4.4.0'

Changing them to this would solve the problem:

s.dependency 'RxSwift', '~> 4.4'
s.dependency 'RxCocoa', '~> 4.4'

How to distinguish tap from scroll in scrollView?

I noticed different behavior between this two parts of code:

  1. view.rx.tapGesture().when(.recognized).subscribe(onNext: { _ in
    self.doSomething()
    }).disposed(by: disposeBag)

  2. view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(doSomething)))

The difference is that (this view is added to UIScrollView) when the user scrolls and taps to stop scrolling 1. approach calls doSomething(), but 2. approach doesn't call doSomething().

For user experience 2. is better, because view is tapped unwittingly in 1. approach while scrolling.
Where does the difference come from? I assume that I should use check simultaneousRecognitionPolicy somehow?

tapGesture in subview and self both triggered

the demo is :

let sub = UIImageView.init(frame: CGRect.init(x: 0, y: 0, width: 200, height: 200))
sub.rx.tapGesture().when(.recognized).subscribe(onNext: { (tap) in

        print("sub tap is \(tap)")
        
    }).disposed(by: disposeBag)
    
    self.view.addSubview(sub)
    
    self.view.rx.tapGesture().when(.recognized).subscribe(onNext: { (tap) in
        
        print("self tap is \(tap)")
        
    }).disposed(by: disposeBag)

when i touch in subview, both tap gesture triggered, Are there any mistakes here?

Support for RxSwift 3.1.0

RxSwift has a newer version out which I would like to use. Can we update RxGesture to use the new version?

PanConfig creation mistype?

.map {recognizer -> RxGestureTypeOption in
                            //current values
                            let newConfig = PanConfig(
                                translation: recognizer.translation(in: control.superview),
                                velocity: recognizer.translation(in: control.superview),
                                state: config.state,
                                recognizer: recognizer)
                            return RxGestureTypeOption.pan(newConfig)
                        }

I think there should be

velocity: recognizer.velocity(in: control.superview),

Am I right ?

Swift 3 Support

Hi,

I just like to know how your plans are about a Swift 3 compatible version?

Thanks

Underplot direct link

Hi,

Just noticed a small error. Your underplot direct link is leading to a github 404 instead of the your actual website.

Awesome idea for the pod.
Thank you,
Francisco

release a 0.1.6

  • test
  • make sure all the new APIs are coherent across the code

Mistype in filtering 'panObservable' ?

Now in UIView+RxGesture.swift we have this

gestures.append(
                            (recognizer, panObservable.filter { gesture in
                                switch gesture {
                                case (.pan(let values)):
                                    return (values.translation.x >= config.translation.x || values.translation.y >= config.translation.y)
                                        && (values.translation.x >= config.translation.x || values.translation.y >= config.translation.y)
                                default: return false
                                }
                            }
                            .bindNext(observer.onNext))
                        )

Both conditions in 'case' are repeated. Should there be velocity checking after && ?

Self is not released when gesture is added to Self itself.

Self is not released when gesture is added to self itself. Have tried capturing self as weak and unowned, but no success.

rx.pinchGesture()
            .asDriver()
            .skip(1)
            .drive(onNext: { [unowned self] recognizer in
                self.pinchGestureHandler(recognizer)
            })
            .disposed(by: rx.disposeBag)

Self is released when moving the subscription to superview of self.

imageView.rx.pinchGesture()
            .asDriver()
            .skip(1)
            .drive(onNext: { [unowned imageView] recognizer in
                imageView.pinchGestureHandler(recognizer)
            })
            .disposed(by: rx.disposeBag)

Wondering is this correct behavior or issue!

Way to access UIGestureRecognizer?

Is there any way to get GestureRecognizer? In some case i want to configure some option like: numberOfTaps, numberOfTouchs or cancelTouchInView...

I see pull request #22 could help.

Discern single from double tap

Hi,
in my view i have to actions, single and double tap.

`self.view.rx
.tapGesture(numberOfTapsRequired: 2)
.when(.recognized)
.subscribe(onNext: { value in

        })
        .addDisposableTo(disposeBag)`

How can I discern them, because Singe and Double always triggers toghether?

Subscribe several times

I use tapGesture in TableView and it calls several times.

cell.ibPlaySound.rx.tapGesture().when(.recognized).subscribe(onNext: {   val  in
                print("play sound....")
}).addDisposableTo(self.binBag)

Touch once and call 3 (or 2) times
play sound....
play sound....
play sound....

OSX support

the pod right now supports only iOS. it must be relatively straight forward to add OSX support

RxGesture podspec does not specify a Swift version.

I'm getting this error during pod install:

[!] Unable to determine Swift version for the following pods:

- `RxGesture` does not specify a Swift version and none of the targets (`MyTarget`) integrating it have the `SWIFT_VERSION` attribute set. Please contact the author or set the `SWIFT_VERSION` attribute in at least one of the targets that integrate this pod.

There's actually two issues here:

  1. RxGesture doesn't set swift_version in the podspec.
  2. CocoaPods is mistaken that MyTarget doesn't set SWIFT_VERSION - it does, but only via an xcconfig file.

The CocoaPods bug is likely going to be more complex to resolve, so would you mind adding swift_version to the podspec in the mean time?

Carthage build is broken

Thanks for the great library!

I'm trying to install it via Carthage using
carthage update --platform iOS and constantly get following error:
#import "Headers/RxCocoa-Swift.h" ^ /Volumes/Workspace/ololo/Carthage/Checkouts/RxGesture/RxGesture/../Carthage/Build/Mac/RxCocoa.framework/Headers/RxCocoa-Swift.h:136:9: error: module 'AppKit' not found @import AppKit; ^ <unknown>:0: error: could not build Objective-C module 'RxCocoa'

Reason for using PermissiveGestureRecognizerDelegate by default?

Question

RxGesture uses PermissiveGestureRecognizerDelegate by default in View+RxGesture.swift#L92. Is there any reason to use this by default?

Background

  1. I used tapGesture() in the subview of UICollectionViewCell.
  2. Start scrolling the collection view.
  3. Tap collection view to stop scrolling.
  4. Unwanted tapGesture() is fired. 😱
  5. To prevent this, I have to create such like ExclusiveGestureRecognizerDelegate and pass it to configuration closure.
  6. Why do we need PermissiveGestureRecognizerDelegate by default? 🤔

Possible Actions

If PermissiveGestureRecognizerDelegate is necessary, I think we could take these actions:

  1. ⚠️ Let users recognize that PermissiveGestureRecognizerDelegate is set by default.
  2. Provide such like defaultGestureRecognizerDelegate to give an opportunity to set default delegate.
  3. Anything else?

And thanks for creating this cool library! 🎉

No Pinch gesture?

Was that an overthought or is it impossible to implement?

I was thinking about giving it a shot, wanted to make sure it wasn't a path that had been taken before

Strange bug with `when` func

I was getting this error, compiling with Xcode 9.0 and RxGesture 1.1.1:


*** DESERIALIZATION FAILURE (please include this section in any bug report) ***
result not found
Cross-reference to module 'RxSwift'
... ObservableType
... E

0  swift                    0x0000000109775dba PrintStackTraceSignalHandler(void*) + 42
1  swift                    0x00000001097751f6 SignalHandler(int) + 662
2  libsystem_platform.dylib 0x00007fffbea3db3a _sigtramp + 26
3  libsystem_platform.dylib 0x000000010d1a0551 _sigtramp + 1316366897
4  libsystem_c.dylib        0x00007fffbe8c2420 abort + 129
5  swift                    0x0000000106e71c51 swift::ModuleFile::fatal(llvm::Error) + 1569
6  swift                    0x0000000106e72102 swift::ModuleFile::getDecl(llvm::PointerEmbeddedInt<unsigned int, 31>, llvm::Optional<swift::DeclContext*>) + 130
7  swift                    0x0000000106e7f08c swift::ModuleFile::getTypeChecked(llvm::PointerEmbeddedInt<unsigned int, 31>) + 1836
8  swift                    0x0000000106e7f4bc swift::ModuleFile::getTypeChecked(llvm::PointerEmbeddedInt<unsigned int, 31>) + 2908
9  swift                    0x0000000106e7fabb swift::ModuleFile::getTypeChecked(llvm::PointerEmbeddedInt<unsigned int, 31>) + 4443
10 swift                    0x0000000106e7f7c2 swift::ModuleFile::getTypeChecked(llvm::PointerEmbeddedInt<unsigned int, 31>) + 3682
11 swift                    0x0000000106e7bfda swift::ModuleFile::getDeclChecked(llvm::PointerEmbeddedInt<unsigned int, 31>, llvm::Optional<swift::DeclContext*>) + 40650
12 swift                    0x0000000106e8aca1 swift::ModuleFile::loadAllMembers(swift::Decl*, unsigned long long) + 657
13 swift                    0x00000001072e4536 swift::IterableDeclContext::loadAllMembers() const + 134
14 swift                    0x000000010733e57c swift::NominalTypeDecl::lookupDirect(swift::DeclName, bool) + 364
15 swift                    0x0000000106e84678 swift::ModuleFile::resolveCrossReference(swift::ModuleDecl*, unsigned int) + 3880
16 swift                    0x0000000106e75b05 swift::ModuleFile::getDeclChecked(llvm::PointerEmbeddedInt<unsigned int, 31>, llvm::Optional<swift::DeclContext*>) + 14837
17 swift                    0x0000000106e720d4 swift::ModuleFile::getDecl(llvm::PointerEmbeddedInt<unsigned int, 31>, llvm::Optional<swift::DeclContext*>) + 84
18 swift                    0x0000000106e7f08c swift::ModuleFile::getTypeChecked(llvm::PointerEmbeddedInt<unsigned int, 31>) + 1836
19 swift                    0x0000000106e7f4bc swift::ModuleFile::getTypeChecked(llvm::PointerEmbeddedInt<unsigned int, 31>) + 2908
20 swift                    0x0000000106e7fabb swift::ModuleFile::getTypeChecked(llvm::PointerEmbeddedInt<unsigned int, 31>) + 4443
21 swift                    0x0000000106e7f7c2 swift::ModuleFile::getTypeChecked(llvm::PointerEmbeddedInt<unsigned int, 31>) + 3682
22 swift                    0x0000000106e7bfda swift::ModuleFile::getDeclChecked(llvm::PointerEmbeddedInt<unsigned int, 31>, llvm::Optional<swift::DeclContext*>) + 40650
23 swift                    0x0000000106e8aca1 swift::ModuleFile::loadAllMembers(swift::Decl*, unsigned long long) + 657
24 swift                    0x00000001072e4536 swift::IterableDeclContext::loadAllMembers() const + 134
25 swift                    0x000000010733e57c swift::NominalTypeDecl::lookupDirect(swift::DeclName, bool) + 364
26 swift                    0x000000010733cf2e swift::DeclContext::lookupQualified(swift::Type, swift::DeclName, swift::NLOptions, swift::LazyResolver*, llvm::SmallVectorImpl<swift::ValueDecl*>&) const + 3518
27 swift                    0x00000001071d1372 swift::TypeChecker::lookupMember(swift::DeclContext*, swift::Type, swift::DeclName, swift::OptionSet<swift::NameLookupFlags, unsigned int>)::$_1::operator()() const + 226
28 swift                    0x00000001071d1239 swift::TypeChecker::lookupMember(swift::DeclContext*, swift::Type, swift::DeclName, swift::OptionSet<swift::NameLookupFlags, unsigned int>) + 281
29 swift                    0x000000010711e239 swift::constraints::ConstraintSystem::lookupMember(swift::Type, swift::DeclName) + 473
30 swift                    0x00000001070eae24 swift::constraints::ConstraintSystem::performMemberLookup(swift::constraints::ConstraintKind, swift::DeclName, swift::Type, swift::FunctionRefKind, swift::constraints::ConstraintLocator*, bool) + 2772
31 swift                    0x00000001070ed1f9 swift::constraints::ConstraintSystem::simplifyMemberConstraint(swift::constraints::ConstraintKind, swift::Type, swift::DeclName, swift::Type, swift::DeclContext*, swift::FunctionRefKind, swift::OptionSet<swift::constraints::ConstraintSystem::TypeMatchFlags, unsigned int>, swift::constraints::ConstraintLocatorBuilder) + 345
32 swift                    0x00000001070eeb8c swift::constraints::ConstraintSystem::simplifyConstraint(swift::constraints::Constraint const&) + 1164
33 swift                    0x00000001070f1429 swift::constraints::ConstraintSystem::simplify(bool) + 105
34 swift                    0x00000001070f2525 swift::constraints::ConstraintSystem::solveRec(llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::FreeTypeVariableBinding) + 53
35 swift                    0x00000001070facd4 swift::constraints::ConstraintSystem::solveSimplified(llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::FreeTypeVariableBinding) + 22132
36 swift                    0x00000001070f272e swift::constraints::ConstraintSystem::solveRec(llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::FreeTypeVariableBinding) + 574
37 swift                    0x00000001070f2122 swift::constraints::ConstraintSystem::solve(llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::FreeTypeVariableBinding) + 354
38 swift                    0x000000010718b127 swift::TypeChecker::solveForExpression(swift::Expr*&, swift::DeclContext*, swift::Type, swift::FreeTypeVariableBinding, swift::ExprTypeCheckListener*, swift::constraints::ConstraintSystem&, llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::OptionSet<swift::TypeCheckExprFlags, unsigned int>) + 8247
39 swift                    0x000000010718b60d swift::TypeChecker::typeCheckExpression(swift::Expr*&, swift::DeclContext*, swift::TypeLoc, swift::ContextualTypePurpose, swift::OptionSet<swift::TypeCheckExprFlags, unsigned int>, swift::ExprTypeCheckListener*, swift::constraints::ConstraintSystem*) + 733
40 swift                    0x000000010718e80e swift::TypeChecker::typeCheckBinding(swift::Pattern*&, swift::Expr*&, swift::DeclContext*, bool) + 366
41 swift                    0x000000010718edcc swift::TypeChecker::typeCheckPatternBinding(swift::PatternBindingDecl*, unsigned int, bool) + 188
42 swift                    0x00000001071a1bc5 (anonymous namespace)::DeclChecker::visit(swift::Decl*) + 1349
43 swift                    0x0000000107210e9d swift::ASTVisitor<(anonymous namespace)::StmtChecker, void, swift::Stmt*, void, void, void, void>::visit(swift::Stmt*) + 13805
44 swift                    0x000000010720cd62 swift::TypeChecker::typeCheckAbstractFunctionBodyUntil(swift::AbstractFunctionDecl*, swift::SourceLoc) + 1090
45 swift                    0x000000010721271b swift::TypeChecker::typeCheckAbstractFunctionBody(swift::AbstractFunctionDecl*) + 475
46 swift                    0x000000010723031a swift::performTypeChecking(swift::SourceFile&, swift::TopLevelContext&, swift::OptionSet<swift::TypeCheckingFlags, unsigned int>, unsigned int, unsigned int, unsigned int, unsigned int) + 2506
47 swift                    0x0000000106d60cc7 swift::CompilerInstance::performSema() + 5031
48 swift                    0x00000001060e5552 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 1378
49 swift                    0x00000001060e3784 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 7716
50 swift                    0x00000001060986a8 main + 12248
51 libdyld.dylib            0x00007fffbe82e235 start + 1
52 libdyld.dylib            0x0000000000000174 start + 1098719040
Stack dump:
0.	Program arguments: ...
...
<lots of stuff>
...

1.	While type-checking 'setupRx()' at /Users/home/Developer/Lottery.com/MUSL/PB&MM/Views/Components/Balls/MUSLMutableTicketBallView.swift:82:13
2.	While type-checking declaration 0x7fdf4212df30 at /Users/home/Developer/Lottery.com/MUSL/PB&MM/Views/Components/Balls/MUSLMutableTicketBallView.swift:86:9
3.	While type-checking expression at [/Users/home/Developer/Lottery.com/MUSL/PB&MM/Views/Components/Balls/MUSLMutableTicketBallView.swift:86:44 - line:90:13] RangeText="rx.model
            .asObservable()
            .flatMap { (model: MUSLMutableNumberBall) -> Observable<Int> in
                model.rx.number.asObservable()
            }"
4.	While loading members for extension of ObservableType in module 'RxGesture'
5.	While deserializing 'when' (FuncDecl #201) in 'RxGesture'
6.	While deserializing decl #667 (XREF) in 'RxGesture'
7.	Cross-reference to module 'RxSwift'
	... ObservableType
	... E
8.	While loading members for extension of ObservableType in module 'RxGesture'
9.	While deserializing 'when' (FuncDecl #204) in 'RxGesture'

I tried changing my code to be more type-explicit; same error. Then I tried removing the RxGesture library completely and it worked. Then I changed the public when function so it does not reference the internal when function (possible recursion-related compiler bug?):

    public func when(_ states: UIGestureRecognizerState...) -> Observable<E> {
        return filter { gesture in
            return states.contains(gesture.state)
        }
    }

...and it works.

Test suite

Add a UI test suite to run though the example app and validate that all gestures work

If I subscribe the tapGesture at a custom view, how can i release the resource in time in case it prevent the dealloc of the custom view.

such as:

class CustomView: UIView {
    init() {
        super.init(frame: CGRect())

        self.creatObservable()
    }

    func creatObservable() {        
        self.rx.tapGesture()
            .takeUntil(rx.deallocated)
            .subscribe({
                print($0)
            })
            .addDisposableTo(rx.disposeBag)
    }
}

or

   func creatObservable() {        
        self.rx.tapGesture()
            .takeUntil(rx.deallocated)
            .subscribe({
                print($0)
            })
    }

How can i release the resource in time in case it prevent the dealloc of the custom view?

Carthage build fail in release 1.0.1

I'm getting the following error with your latest release(1.0.1) using Carthage.
it was working before so I have to explicitly specify 1.0.0 in my Cartfile which is not my preferred way.

Building scheme "RxGesture-iOS" in RxGesture.xcodeproj
Build Failed
Task failed with exit code 65:
/usr/bin/xcrun xcodebuild -project PATH_AO_APP/Carthage/Checkouts/RxGesture/RxGesture/RxGesture.xcodeproj -scheme RxGesture-iOS -configuration Release -derivedDataPath ../Caches/org.carthage.CarthageKit/DerivedData/RxGesture/1.0.1 -sdk iphoneos ONLY_ACTIVE_ARCH=NO BITCODE_GENERATION_MODE=bitcode CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES clean build

I tried to build it and the error is PATH_TO_APP/Carthage/Checkouts/RxGesture/Pod/Classes/View+RxGesture.swift:102:22: error: value of type 'Observable' has no member 'bind'
.startWith(gesture)

FYI:
I had a look into the file and compared with the previous version

                let disposable = genericGesture.rx.event
                    .map { $0 as! G }
                    .startWith(gesture)
                    .bindNext(observer.onNext)

has been changed to:

                let disposable = genericGesture.rx.event
                    .map { $0 as! G }
                    .startWith(gesture)
                    .bind(onNext: observer.onNext)

rollback works so if I change this line build succeeds

tapGesture() immediately send event

I have a question, why there RxGesture/Pod/Classes/View+RxGesture.swift:100 is call ".startWith(gesture)"?

public func gesture<G: GestureRecognizer>(_ gesture: G) -> ControlEvent<G> {
      .....
        let source: Observable<G> = Observable
            .create { observer in
                MainScheduler.ensureExecutingOnScheduler()

                control.addGestureRecognizer(gesture)

                let disposable = genericGesture.rx.event
                    .map { $0 as! G }
                   >>>>>> .startWith(gesture) <<<<<<
                    .bind(onNext: observer.onNext)

                return Disposables.create {
                    control.removeGestureRecognizer(gesture)
                    disposable.dispose()
                }
            }
            .takeUntil(deallocated)

        return ControlEvent(events: source)
    }
}

I am binding tap gesture on my view to show another controller and it is called immediately after initialisation of view:

self.rx.tapGesture()
                .asObservable()
                .toVoid()
                .subscribe(onNext: {
                     router.showShoppingList()
                })
                .disposed(by: disposeBag)

Is it possible to subscribe to UIButton UIControlEvents(.touchUpInside, .touchDown, .touchUpOutside, etc..)?

Hi here,

Is it possible to subscribe to UIButton UIControlEvents(.touchUpInside, .touchDown, .touchUpOutside, etc..)?

otherwise there is still need to write boilerplate

button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
button.addTarget(self, action: #selector(buttonDown), for: .touchDown)
button.addTarget(self, action: #selector(buttonUp), for: .touchCancel)
button.addTarget(self, action: #selector(buttonUp), for: .touchUpOutside)

for example right now I can subscribe to .rx.tapGesture().asControlEvents... but this will give me only UITapGestrureRecognizer 😞.

RxSwift version conflicts with Moya

[!] Unable to satisfy the following requirements:

- `RxSwift (~> 3.0.0)` required by `RxGesture (0.2.0)`
- `RxSwift (~> 3.1.0)` required by `Moya/RxSwift (8.0.0)`

multiple SwipeGestures

Hello, thanks for this library.

I'm trying to recognise multiple swipe gestures on the same view and create an observable of the latest recognised swipe's direction.

I can do it with an Observable.merge but it is pretty verbose and I was hopping to be able to do something like:

let observableDirection = self.view.rx.swipeGesture([.left, .right, .up, .down]).when(.recognized).map { $0.direction }

but that doesn't seem to work: up and down events are not emitted and left and right return a direction with rawValue of 15

Not sure if this is a bug or if I missed something ?

Pan gesture type ?

Sorry in advance for a very basic question, but I'm having some trouble with the following:

class SomeView: UIView {
  var panGesture: [WHAT IS THE TYPE]!

  override init(frame: CGRect) {
    // ...
    self.panGesture = self.rx_gesture(.Pan(.Changed))
    // ....
  }
}

What type should panGesture be declared as ? I tried:

- ControlEvent<RxGestureTypeOption>  => undeclared type 'ControlEvent'
- Observable<RxGestureTypeOption> => cannot assign value of type 'ControlEvent<RxGestureTypeOption> to type 'Observable<RxGestureTypeOption>'

Thanks

tvOS Compatibility

Are there any known issues for migrating parts of this (press, long press, swipe) to tvOS?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.