-
[iOS/Swift] RxGesture - Gesture가 동시에 인식되는 문제야매 iOS 2023. 8. 7. 20:14
문제
environment
UIScrollView가 있고 subview로 UITextField를 가짐
UIScrollView에 rx.tapGesture를 사용해 TapGesture 적용
- UIScrollView를 탭했을 때 키보드를 내리기 위해
problem
UITextField를 터치했을 때 interaction이 어색함
해결
TL;DR
scrollView.rx.tapGesture() // 수정 전 scrollView.rx.tapGesture(configuration: { _, config in // 수정 후 config.simultaneousRecognitionPolicy = .never })
config.simultaneoulsyRecognitionPolicy 프로퍼티에 .never를 넣어주면 됨
RxGesture
RxGesture는 configuration을 설정할 수 있는 구조로 되어 있음
extension Reactive where Base: RxGestureView { public func tapGesture(configuration: TapConfiguration? = nil) -> TapControlEvent { gesture(make(configuration: configuration)) } }
Configuration
RxGesture에서 Configuration은 클로저로 구성되어 있다.
- GestureRecognizer와 Delegate를 인자로 받는 클로저
typealias Configuration<Gesture: RxGestureRecognizer> = (Gesture, GenericRxGestureRecognizerDelegate<Gesture>) -> Void
사용할 때 GestureRecognizer 또는 Delegate에 접근해서 값을 커스텀할 수 있다.
GenericRxGestureRecognizerDelegate
UIGestureRecognizerDelegate에 대응되는 값들을 갖고 있다
struct GestureRecognizerDelegatePolicy { private init policy: @escaping PolicyBody) { self.policy = policy } public static var always: GestureRecognizerDelegatePolicy<PolicyInput> { .init { _ in true } } public static var never: GestureRecognizerDelegatePolicy<PolicyInput> { .init { _ in false } } func isPolicyPassing(with args: PolicyInput) -> Bool { policy(args) } } final class GenericRxGestureRecognizerDelegate<Gesture: RxGestureRecognizer> RxGestureRecognizerDelegate { ... simultaenousRecognitionPolicy: GestureRecognizerDelegatePolicy<(Gesture, RxGestureRecognizer)> = .always public func gestureRecognizer( _ gestureRecognizer: RxGestureRecognizer, shouldRecognizeSimultaenouslyWith otherGestureRecognizer: RxGestureRecognizer ) -> Bool { simultaenousRecognitionPolicy.isPolicyPassing (with: (gesture as! Gesture, otherGestureRecognizer)) } }
해결
shouldRecognizeSimultaenouslyWith otherGestureRecognizer 의 default value가 .always 였으므로 이벤트를 UITextField도 받고 UIScrollView도 받아서 생기는 문제였음
→ 프로퍼티의 값을 .always(true)에서 .never(false)로 변경하니 UITextField의 Gesture와 UIScrollView에 적용된 TapGesture가 동시에 인식되지 않아 문제 해결
UIGestureRecognizerDelegate의
gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer)
디폴트 값은 false이지만 RxGesture에선 true로 설정되어 있음실제 Delegate과 defaultValue가 다르므로 이 메서드뿐만 아니라 다른 메서드를 사용할 때도 주의해서 사용해야 함
'야매 iOS' 카테고리의 다른 글
[iOS/Swift] RxSwift subscribe flow (0) 2023.08.07 [Swift] Dispatch (0) 2023.08.07 [Swift] Copy on Write (0) 2023.08.07 [iOS/Swift] SwiftUI 계산기 (0) 2023.08.07 [iOS] Certificate & Provisioning (0) 2023.08.07