LoginSignup
21
15

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-09-26

はじめに

こんにちは :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などで自動計算されたりと混乱してしまいますが、少しずつ慣れていけたらと思います。

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

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

21
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
15