0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

IBOutletで接続しているBarButtonItemがいつの間にかnilになる

Posted at

この記事の内容

  • IBOutletで接続しているBarButtonItemがnilになる原因と対策
  • navigationItem.rightBarButtonItemやleftBarButtonItemには気をつけよう!
  • IBOutletにweakをつけた時とつけなかった時の挙動の違い

この記事のターゲット

  • BarButtonItemがいつの間にかnilになるんだけど?!って人
  • IBOutletってweakつける意味ある?!って人
  • 俺(備忘録)

発生している問題

@IBOutlet** weak **var** barButton: UIBarButtonItem! のように定義しているオブジェクトがいつの間にかnilになっており、参照しようとするとクラッシュしてしまう。
weakを外して@IBOutlet var barButton: UIBarButtonItem!とするとクラッシュしない。

問題の原因

navigationItem.rightBarButtonItem = hogeButton と別のButtonを入れていたから!

詳細

元々storyboard上でnavigationItemのrightBarButtonItemにbarButtonを適用し、NavigationBarの右側にbarButtonが表示されるように設定していた。

しかし仕様上、ある動作をした時に表示されているボタンをbarButtonからhogeButtonへ変更させたいためnavigationItem.rightBarButtonItem = hogeButtonと実装していた。

この時、内部ではrightBarButtonItemからbarButtonが削除される → すなわちNavigationItemからbarButtonに対する強参照が解除されることになり、barButtonがメモリ解放されてしまう。

問題の対策

barButtonの宣言時にデフォルトでついているweakを削除し、barButtonへの参照を強参照とする
また、万が一で循環参照するかもしれないので、barButtonを宣言しているViewControllerのdeinit内でbarButton = nil を行い参照カウントを減らしておく。

なぜweakを削除するとクラッシュしないの?

先ほどの話では、navigationItem.rightBarButtonItem = hogeButtonとしたときに、NavigationItemからbarButtonに対する強参照が解除されるのでbarButtonのメモリ解放が発生すると説明しました。

しかし正確には、NavigationItemからbarButtonに対する強参照が解除されるからbarButtonのメモリ解放が発生するわけではなく、barButtonに対する強参照が解除されたことにより、barButtonの参照カウントが0になるからメモリが解放されます。
そこで、barButtonのweakを外すことで

  • NavigationItemからの参照カウント
  • UIViewControllerからの参照カウント

の2つが与えられるので、NavigationItemからの参照カウントが無くなってもbarButtonのメモリが解放されることはなくなります。

IBOutletにweakをつけた時とつけなかった時の挙動の違い

おまけですが、IBOutletにweakをつけた時とつけなかった時の違いについて軽く解説します。

weakをつけた時(デフォルト)のメリット

  • 循環参照が発生しづらくなる
    • weakをつけた対象オブジェクトに対する参照は(一部を除き)すべてが弱参照となるため、循環参照が発生しづらくなる

weakをつけた時(デフォルト)のデメリット

  • weakをつけなかった時よりもnilにアクセスする可能性が上がる
    • 基本的にはないが、なんらかのきっかけで対象オブジェクトの参照カウントが0になってしまった場合にメモリが解放され、nilにアクセスしてしまう

weakをつけなかった時のメリデメは上記の逆です。
正確に管理しないと循環参照が発生しやすくなる代わりに、nilにアクセする可能性が下がります。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?