LoginSignup
0
3

More than 5 years have passed since last update.

Swiftはnull安全だけどCocoaはそうじゃない話

Posted at

swiftはnull安全な言語なので、nullの変数にアクセスしてしまって落ちる・・・ということがないはずなのですがCocoaの内部でnullアクセスしてアプリが落ちることがあります・・・
その罠のひとつを紹介したいと思います。

例えば何かのビューの上にマウスカーソルを持ってきた時、すぐさまポップアップを表示するのではなく少し遅延させて表示したい場合があると思います。(以下の例では1秒遅延)
その場合にダメな例と良い例のサンプルが以下。

sample.swift
class sampleView: NSView
{
    let popover = NSPopover()

    //ダメな例
    func showPopover_NG() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
            guard let _self = self else { return }
            _self.popover.show(relativeTo: NSRect.zero, of: _self, preferredEdge: .minX)
        }
    }

    //良い例
    func showPopover_OK() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
            guard let _self = self, _self.window != nil else { return }
            _self.popover.show(relativeTo: NSRect.zero, of: _self, preferredEdge: .minX)
        }
    }
}

ダメな例がなぜダメか、というと
popover.showが実行されるその瞬間にsampleViewのwindowがnullになっていることがあるからです。
sampleViewのwindowがnullになっていると、popover.showした途端にアプリが落ちます。popover.showは内部的にsampleViewのwindowにアクセスしているようです。

本来的には「sampleViewのwindowがnullであるならshowは無視される」というcocoaフレームワークの挙動になっていれば良いのですがそうはしてくれないのがApple。

ですので、showの前にwindowのnullチェックが必要になります。このnullチェック、何のためにやっているのかあとからソースを見た人がわからなくなるのでやりたくないんですが・・・

0
3
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
0
3