iOS11.0에 UINaviation Controller라고 불리지 않은 TitleView의 터치 이벤트에 대한 현상

개시하다


안녕하세요
UINaviationController에는 TitleView 속성이 있습니다.
저는 NavigationBar의 중앙에 오기 위해 TitleView에 xib로 UIButton을 포함한 독특한 사용자 정의 View를 제작하여 다음과 같이 활용했습니다.

iOS11.0 이전에 이 버튼을 누르면 문제 없이 작업을 할 수 있습니다
이후 터치 이벤트는 반응이 없었던 것 같다.
※ 코드로 타이틀뷰를 제작할 때 타이틀뷰 크기를 충분히 얻으면 iOS 11.0도 예전과 마찬가지로 터치 이벤트라고 합니다.

MainViewController.swift
override func viewDidLoad() {
    super.viewDidLoad()
    let button = UIButton()
    button.setTitle("Button", for: .normal)
    button.frame.size = CGSize(width: 60, height: 30)
    button.addTarget(self, action: #selector(MainViewController.buttonAction), for: .touchUpInside)
    let titleView = UIView()
    titleView.backgroundColor = UIColor.cyan
    //十分な大きさを確保
    titleView.frame.size = CGSize(width: 120, height: 44)
    titleView.addSubview(button)
    button.frame.origin = CGPoint(x: titleView.frame.size.width * 0.5 - button.frame.size.width * 0.5,
                                  y: titleView.frame.size.height * 0.5 - button.frame.size.height * 0.5)
    self.navigationItem.titleView = titleView
}

해결책


TitleView에 대한 사용자 정의 View의 intrinsinsic ContentSize를 설정한 후
iOS11.0 이전과 마찬가지로 터치 이벤트라고 합니다.
TopBarView.swift
override var intrinsicContentSize: CGSize {
    return CGSize(width: 134, height: 33)
}

시도해 본 일

  • iOS11.0isUserInteractionEnabled의 기본값이 바뀌었는지 고려
    UINaviationBar 등true
  • //デフォルトでtrueなので結果は ×
    navigationItem.titleView?.isUserInteractionEnabled = true
    //デフォルトでtrueなので結果は ×
    navigationController?.navigationBar.isUserInteractionEnabled = true
    
  • UITApGesture Recognizer
  • 설정 시도
    //結果は ×
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(MainViewController.topBarTap))
    self.navigationItem.titleView?.addGestureRecognizer(tapGesture)
    

    샘플 코드


    먼저 샘플의 코드를 쓰세요.
    혼자 만든 뷰(TopBarView)도 별도의 xib 파일에서 제작됐다.
    MainViewController.swift
    import UIKit
    
    class MainViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.navigationItem.titleView = TopBarView.instantiate()
        }
    }
    
    TopBarView.swift
    import UIKit
    
    class TopBarView: UIView {
    
        @IBOutlet weak var button: UIButton!
    
        override func awakeFromNib() {
            button.setTitle("Button", for: .normal)
        }
    
        static func instantiate(withOwner ownerOrNil: Any? = nil) -> TopBarView {
            let nib = UINib(nibName: "TopBarView", bundle: nil)
            return nib.instantiate(withOwner: ownerOrNil, options: nil)[0] as! TopBarView
        }
    
        private override init(frame: CGRect) {
            super.init(frame: frame)
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override var intrinsicContentSize: CGSize {
            return CGSize(width: 134, height: 33)
        }
    
        @IBAction func buttonAction(_ sender: Any) {
            print("ボタンが押されました")
        }
    }
    

    최후


    iOS11.0이 된 UINaviation Controller에는 레이지 타이틀, Navigation Bar의 높이를 UIScrollView 등으로 자동 계산하면 혼란스러울 수 있지만 조금이라도 익숙해졌으면 좋겠다.

    참고 자료

  • UITapGestureRecognizer on navigationItem.titleView not working on iOS 11 - stackoverflow
  • iOS 11.0 GM: Subviews of UINavigationItem's titleView don't receive touch events? - stackoverflow
  • 시청해 주셔서 감사합니다.

    좋은 웹페이지 즐겨찾기