anz blog

WKWebViewをモーダル表示していると意図せぬ時に画面ごと閉じられる

2018-03-14 #Swift

タイトルの通り(え?何言ってるかわからない?)なのですけど....。
特に解決策とかはなく(わからない)、ただの愚痴というか報告というか(笑)

WKWebViewをモーダル表示しているとリンクとか画像とかを長押ししたときに表示されるメニューを閉じるといっしょに画面も閉じられる

です。 中身のある話でもないので、先に結論だけ...iOS11のバグらしいです

環境

  • Xcode v9.2
  • iOS 11

問題

どんな問題なのか...言葉よりも見てもらったほうがはやいので...

bug_wkwebview

勝手に閉じられる!(もちろん閉じるコードは書いていない)
これだとリンクでやってるけど、画像長押しも同じ。
多分ActionSheetっぽいやつが出る操作は全部こうなるのじゃないかな...

再現コード

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .lightGray
        let button = UIButton(type: .custom)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle("Push me!", for: .normal)
        button.setTitleColor(.black, for: .normal)
        button.addTarget(self, action: #selector(type(of: self).tap), for: .touchUpInside)
        self.view.addSubview(button)
        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
        ])
    }

    @objc func tap() {
        let vc = WebViewController()
        self.present(vc, animated: true, completion: nil)
    }
}

class WebViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let webView = WKWebView(frame: .zero)
        webView.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(webView)
        NSLayoutConstraint.activate([
            webView.topAnchor.constraint(equalTo: self.view.topAnchor),
            webView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
            webView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
            webView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)
        ])
        webView.load(URLRequest(url: URL(string: "https://google.com")!))
    }
}

どこにもdismiss(animated:,completion:)なんぞは書いていません😇

ごにょごにょ

なんだろうなーとググっていると、iOS11のバグっぽいのですよね。

9月だから結構前ですね...簡単に直せそう(しらんけどw)だけど、いまも元気に発生中です。

ちなみに

UIWebViewだったら大丈夫ですし、SFSafariViewControllerなんぞも大丈夫です
iOS10とかでも問題ないです。

なにか無いのか....?

無い!(わからん!

やるとしたら、このアクションシートを出さないようにするって言う感じですかね...。
-webkit-touch-calloutとかっていうCSSプロパティをさしこむとでなくなるんだとか。。。

いや、あるだろ?本当は。。!?

無理やりなハック的な手法として...
ViewControllerのpresent(_ viewControllerToPresent:, aninmated flag:, completion:)をoverrideして自分で何かするっていう方法があります...

override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
    let className = String(describing: type(of: viewControllerToPresent))
    if "WKActionSheet" == className {
        // something...
    } else {
        super.present(viewControllerToPresent, animated: flag, completion: completion)
    }
}

こういう感じ?
これで一応何かできそうですけど...
何を長押ししたのかわからないですし...
WKActionSheetがprivateなやつなので何者かよくわからんですし...
ほかにどんなケースでこいつが呼ばれるかもわかんないですし...
正直この方法はやらないですね(笑)

座して直るのを待つのみ!
なにか回避策をご存じの方は是非!!

追記(2018.04.02)

iOS 11.3 でたけど、それでもまだ発生する...😇

追記(2018.05.22)

iOS 11.3.1 で今度こそ!?...ダメでしたね...
Xcode 9.3.1 で合わせて確認してみたけど...かわらないですね🤤

追記(2018.06.01)

iOS 11.4 と併せて Xcode 9.4 がでてきましたね!
...だめでしたね!!
直る日はこないのかもしれない...

追記(2018.09.20)

iOS 12 で修正されているのを確認しました!
Xcode 9.4 でビルドしたものでも iOS 12 だと期待している挙動になるので、
ビルドした Xcode のバージョンは関係なさそうです。