Edited at

iOS11.0でUINavigationControllerのTitleViewのタッチイベントが呼ばれない現象について

More than 1 year has passed since last update.


はじめに

こんにちは :leaves:

UINavigationControllerにはTitleViewというプロパティがあります。

私はNavigationBarの中央に来るようTitleViewUIButtonを含む独自のカスタムViewをxibで作成して以下のように利用していました。

Group.png

iOS11.0以前ではこのボタンは押すことができ、問題なく動作するのですが、

以降ではTouchEventがどうやら反応しないようです。

※ コードでTitleViewを作成している場合、TitleViewの大きさを十分に取っていればiOS11.0でも以前と変わらずTouchEventは呼ばれます

group2.png


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のintrinsicContentSizeを設定すると

iOS11.0以前と同じくTouchEventが呼ばれるようです。


TopBarView.swift

override var intrinsicContentSize: CGSize {

return CGSize(width: 134, height: 33)
}


試してみたこと


  • iOS11.0でisUserInteractionEnabledのデフォルト値が変わったのかと考え、
    UINavigationBar等をtrueにしてみる

//デフォルトでtrueなので結果は ×

navigationItem.titleView?.isUserInteractionEnabled = true
//デフォルトでtrueなので結果は ×
navigationController?.navigationBar.isUserInteractionEnabled = true


  • UITapGestureRecognizerを設定してみる

//結果は ×

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(MainViewController.topBarTap))
self.navigationItem.titleView?.addGestureRecognizer(tapGesture)


サンプルコード

一応サンプルのコードを書いておきます。

独自に作成したView(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になりUINavigationControllerにLargeTitleが追加されたり、NavigationBarの高さ分がUIScrollViewなどで自動計算されたりと混乱してしまいますが、少しずつ慣れていけたらと思います。


参考にさせていただいた記事

見て頂いてありがとうございます。