SwiftはARCでメモリを管理しています。従って下手な書き方をすればメモリリークがいとも簡単に発生します。 どのようにメモリリークを防ぎますか?コーディング規約、コードレビュー、最後の砦のQA… 勿論、我々は怠惰なので、努力や根性よりも、自動的に動作するものを好みます。第四の方法として、Mirrorを使ったテストケースの実装を紹介します。
最近のタスクはコードを書くなくなってリファクタリングやコードレビュー、ペアプロ、プロデューサーとのコミュニケーションなど。
スマブラとスプラトゥーンやっていたのが1ヶ月前、2倍で大変だったが、FF14もやって3倍になっています
アイコンが何に見えるか、みなさんに聞いてみました
ドラゴン?
実はナメクジがヘッドホンで音楽を聞いています。
左側の解釈を聞いてから、僕自身、左に見えると思っていますが、右、ナメクジです。
一つの画面をマイクロサービスで再現する取り組みを去年のiOSDCで発表しました。
これはメモリリークする。
ガベージコレクションがない。
たまにこの話をするとARCはガベージコレクションだという人も居るが、話がややこしくなるのでその話はやめましょう。
ガベージコレクションがない代わりにどうメモリを開放しているのか、リファレンスカウンティングですね
WindowがRootViewControllerをもっていてRootViewControllerが次に出したい画面をもっていたりする。
リファレンスをもっている、それによってオブジェクトを生存させている。
リファレンスが消えると
消える
それによってまたリファレンスカウントがなくなったものがきえて
きれいになる
さっきのコードを見てみましょう
循環参照が出来てしまっってずっと残り続ける
さっきの図にこの参照を入れてみました
なのでWeakを入れましょう
コードレビューで防ぐ、コーディングルールにする、handlerでweakを必須とする、Lintルールを活用する、MemoryGraphDebuggerをつかって起きてしまったものに対処していくこともできる
でもすごく時間がかかって面倒
ミラーとウィークの箱を使います
ミラーはSwiftにおけるRefrectingの機能。
画面を鏡に写すとニョロっと全プロパティが見えるように成る
それらをweakリファレンスの箱にいれる
それでもとがなくなれば
全部消えるはず
出来上がったものがあります
XCTAssertNoLeakをimportします。
。。。デモは動かないというジンクスがありますが...早速Xcodeの補完がうまく働いていません。。
なんでFailするの
こちらで確認してください、時間があればもう一度あとで。
AssertNoLeak作りました。作るまでに乗り越えなければ行けない壁があって、Swiftのasの不思議な挙動に立ち向かう、というのがあります。
weak box に値を詰める、値を詰めるためにclassを詰める必要がある。でもミラーで取得できるのはany。
AnyObjectにキャストすると、すべてのものがAnyObjectにキャストできるようになってしまった。
type(of:)を使うと
isを使ってみる
引数に渡ってきたオブジェクトの型を確認する。
AnyObjectの型かと聞くと割と正直に答えてくれる。Structを渡すと、違います、となる
次は、OptionalをUnwrapしたい
Optionalはenum。Optionalの向う側にあるものがほしい。
なのでanyで渡ってきたargからOptionalの向う側にある値を取り出さなくてはいけない
キャストしてみた。全くうまくいかない
Optional
Optionalを取り巻くsubtypingルールは2つある
中身の値にsubtyping関係があるときにString?はAny?にキャストできる
これはコンパイラの気持ちがわかっていない
コンパイラの気持ちになると、実はString?からAny?へのキャストではなく、Anyから
こういう動きをしているので、まだOptionalが入っているということに成る
Mirrorを使うとオプショナルであるということが分かる。
Optionalは一つしか値を持っていないので先頭を取り出せばいい
ダメなこともある
IUOは今は滅びたが、昔のコードにはある、Optionalの中にIUOが入っている
OptionalKindというProtocolを作る
これにキャストするとうまく言う
XCTAssertNoLeakを作り、動かないデモをしました AnyObjectへのキャストとOptionalへのキャスト
サポートバージョン
会社で作って運用していた。4.2にしたら全部動かないことが起きた。なぜか
ミラーでweakなプロパティにアクセスするとretainされる
リファレンスカウントが1増えてしまう
ミラーを使ってメモリリークのテストをしようとしたら、関数を通すとメモリリークが起きる。
おあとがよろしいようで、ありがとうございました。