Successfully reported this slideshow.
Your SlideShare is downloading. ×

Xcodeで値を表示する

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Xcodeで値を表示する

  1. 1. Xcodeで値を表示する 「iOS 11 Programming」刊行記念 Night
  2. 2. 自己紹介 ● 荒巻 賢一 ● 趣味 ○ ピアノ、テニス、競技プログラミング、ボルダリング ● ライフワーク ○ デバッグ
  3. 3. Agenda ● Xcodeで値を表示することについて調べてみた
  4. 4. ある日の不具合 ● safeAreaInsetsが反映されない ○ UIScrollViewのsubviewにSafeAreaInsetが反映されないこ とがある
  5. 5. View Hierarchyで見る ● あるviewまではsafeAreaInsetsが 正しく、subviewで正しくない
  6. 6. View Hierarchyで見る Viewを右クリックし、Print Descriptionで idがわかる Printing description of $12: <UIView: 0x7fde56eaad00; frame = (0 0; 812 375); autoresize = W+H; layer = <CALayer: 0x60000043a3e0>>
  7. 7. デバッグコンソールで調べる ● デバッガからexpressionコマンド (短縮形: pまたはpo)で確認して みる
  8. 8. idからsafeAreaInsetsを調べる エラー (lldb) p [0x7fde56eaad00 safeAreaInsets] error: warning: receiver type 'long' is not 'id' or interface pointer, consider casting it to 'id' error: no known method '-safeAreaInsets'; cast the message send to the method's return type
  9. 9. idからsafeAreaInsetsを調べる idでキャストしろと言われたのでやってみる (lldb) p [(id)0x7fde56eaad00 safeAreaInsets] error: no known method '-safeAreaInsets'; cast the message send to the method's return type
  10. 10. idからsafeAreaInsetsを調べる UIViewにキャストしてみる (lldb) p [(UIView*)0x7fde56eaad00 safeAreaInsets] (UIEdgeInsets) $13 = (top = 32, left = 0, bottom = 21, right = 0)
  11. 11. idからsafeAreaInsetsを調べる しかしsuperviewでは正常に出力されない (lldb) p [[(UIView*)0x7fd688f0e670 superview] safeAreaInsets] (UIEdgeInsets _Nullable) $14 = {}
  12. 12. idからsafeAreaInsetsを調べる 戻り値をキャストすればよかった (lldb) p (UIEdgeInsets)[0x7fde56eaad00 safeAreaInsets] (UIEdgeInsets) $15 = (top = 32, left = 0, bottom = 21, right = 0) (lldb) p (UIEdgeInsets)[[0x7fde56eaad00 superview] safeAreaInsets] (UIEdgeInsets) $16 = (top = 32, left = 44, bottom = 21, right = 44) 戻り値の型がid以外のときはキャストが必要
  13. 13. 疑問 ● なぜこのような違いが生まれるのか? ● expressionコマンドは何をしているのか?
  14. 14. LLDBをビルドしてみる ● XcodeのデバッガはLLDB ○ https://lldb.llvm.org/ ● デバッガをステップ実行させれば挙動がわかるので は? ※ XcodeのLLDBとは一部異なる可能性があります
  15. 15. LLDB上でLLDBを実行する ● LLDB in LLDB LLDB in LLDB(黒) XcodeのLLDB(青)
  16. 16. ブレークポイントを設定する ● Expressionコマンドに関係しそうな場所にブレーク ポイントを設定してステップ実行してみる ○ UserExpression::Evaluate
  17. 17. expressionコマンドの式の処理 1. 式をコンパイルする 2. メッセージを組み立てる 3. オブジェクトにメッセージを送る 4. 結果を表示する
  18. 18. 式をコンパイルする ● パースして構文木(Clang AST)を得る ○ ClangExpressionParser::Parse ● 文法エラーや、存在しないセレクタを指定した場合 はここでエラーになる
  19. 19. メッセージを組み立てる (インラインアセンブラ) 1. オブジェクトのクラスを取得する 2. respondsToSelector:でYESを返すかどうか調べる 3. メッセージを送る AppleObjCRuntimeV2::CreateObjectChecker
  20. 20. 戻り値のための領域を準備する ● 呼び出し規約により場合わけ ○ ObjcObjectChecker::InstrumentInstruction ○ idのとき eMsgSend_fpret ○ 構造体のとき eMsgSend_stret ■ safeAreaInsetsはこっち
  21. 21. オブジェクトにメッセージを送る ● ターゲットプログラム上に新しいスレッドを作って オブジェクトにメッセージを送る ○ UserExpression::Execute
  22. 22. 結果を表示する ● ValueObject::Dump ● CommandInterpreter::PrintCommandOutput
  23. 23. 余談: 実行できるがデバッガで表示できない ● respondsToSelector: にNOを返すと表示できない ○ 例えばNSProxyを継承してrespondsToSelector: が未実装のとき
  24. 24. デバッグオプション (--debug or -g) メッセージ送信のコードが見られる (lldb) expression --debug -- [view safeAreaInsets] Execution was halted at the first instruction of the expression function because "debug" was requested. Use "thread return -x" to return to the state before expression evaluation.
  25. 25. まとめ ● 値を表示するときにも動的にコンパイルと実行が行 われている ● safeAreaInsetsの表示にキャストが必要なのは、呼 び出し規約の違いに起因している
  26. 26. ● iOS Engineer ● Android Engineer ● Web, Front-end & Back-end ● Site Reliability ● Ad Services ● Machine Learning ● and more…! https://smartnews.workable.com We’re Hiring!We’re Hiring!

×