문제
현재 회사에서 개발중인 앱에는 가로 스크롤이 가능한 스크롤뷰(콜렉션뷰 포함)들이 각 화면에 다양하게 존재하고 있습니다.
문제는 기기의 왼쪽 엣지를 오른쪽으로 쓸어넘겨서 뒤로가기(interactivePopGesture
)를 하고 싶어도 할 수가 없고 스크롤뷰의 가로방향 팬제스처만 인식한다는 겁니다.
특히 화면 전체를 가로 스크롤 가능한 콜렉션뷰가 덮고 있는 화면들이 좀 있는데요.
이 경우에는 특히나 사용성이 떨어집니다. 반드시 좌상단에 있는 뒤로가기 버튼을 탭해줘야만 네비게이션의 이전 스택으로 팝을 할 수 있기 때문이죠.
해결
방법은 간단합니다. UIGestureRecognizerDelegate
의 메소드 중 두 제스처인식기가 인식되었을 때 그 중 하나의 인식을 실패하게 할 지를 결정하는 메소드 gestureRecognizer(_: shouldBeRequiredToFailBy:)
를 오버라이드 하여 원하는 때에 팬 제스처를 실패하게 해주면 됩니다.
UIGestureRecognizerDelegate
를 채택하는 UINavigationController
의 서브클래스를 만듭니다.
import UIKit
typealias UINavigationController = PopGestureableNavigationController
class PopGestureableNavigationController: UIKit.UINavigationController {
override init(rootViewController: UIViewController) {
super.init(rootViewController: rootViewController)
setNavigationBarHidden(true, animated: false)
interactivePopGestureRecognizer?.delegate = self
}
required init?(coder aDecoder: NSCoder) {
return nil
}
}
extension PopGestureableNavigationController: UIGestureRecognizerDelegate {
func gestureRecognizer(
_ gestureRecognizer: UIGestureRecognizer,
shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer
) -> Bool {
return viewControllers.count > 1 ? true : false
}
}
이제 앱 전체의 모든 UINavigationController를 PopGestureableNavigationController로 바꿔주면 되는데요. 꾀나 번거로울것 같군요. 그래서 저는 하지 않았습니다. 그대신 스코프(Scope) 우선순위를 해킹하는 방법으로 다음 코드 한 줄만 작성했습니다.
typealias UINavigationController = PopGestureableNavigationController
자세한 내용은 전수열님의 글을 참고했습니다.
iOS 13 에서 변경된 UIModalPresentationStyle 해킹하기
댓글