ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
XcodeとLLDBでの高度なデバッグ
高度なテクニックや、Xcodeでのデバッグワークフローを向上させるためのヒントとコツを紹介します。また、LLDBとカスタムブレークポイントを活用したより高度なデバッグ方法や、Xcodeのビューデバッガツールを最大限に活用し、AppのUIの問題をより効果的に解決する方法についても紹介します。
リソース
関連ビデオ
WWDC22
WWDC21
WWDC19
WWDC18
-
ダウンロード
(音楽)
(拍手) こんにちは “Advanced Debugging with Xcode and LLDB”へようこそ Xcodeチームの クリス・マイルズです このセッションの後は Bashですね 時間どおりに終わらせます 盛りだくさんなので さっそく始めましょう まずは Swiftデバッグの信頼性です いいお知らせがあります Xcode 10の信頼性を 大幅に向上させました
ええ そうなんです (拍手) Swiftデバッグにおける エッジケースを解消しました いくつかお話しします 複雑なプロジェクトや ビルド設定のケースです コンソールでpoの使用や 式の評価を試みると このようなエラーが 発生します この“AST context”とは コンパイラの状態の再構成のため 必要な式のコンテキストです モジュールの衝突などで― 式のコンテキストが再構成できず 失敗するのです Xcode 10ではLLDBが フォールバックを実装 より簡単なコンテキストを 現在のフレームに作り 式の評価に使用します また デバッグ中に 変数の型を― マテリアライズできないことも あります Xcodeでは このような表示です 左側の変数ビューに 変数名が並んでいますが― 型や値は 表示されていませんね このようなエラーでは 変数の値が出力できません
デバッグ情報が 生成されなかった問題も― 皆さんのレポートのおかげで 解決できました デバッグ中に遭遇したバグを 報告してくださり― 感謝します Xcode 10の問題を 見つけた場合は― 今後も報告してください WWDCにご参加中なら ラボに お立ち寄りを 明日の午前9~12時に ラボを実施します 皆さんのプロジェクトを エンジニアに見せてください
それでは私が気に入っている デバッグの秘訣を― 皆さんにお教えしましょう 話すだけでなく デモをご覧に入れます
(拍手)
使うのは Solar Systemという iOSのアプリケーションです WWDCでご覧になった方も いるでしょう その中のMoon Jumperの デバッグです まずスマホを持って ジャンプします するとジャンプの力が 月の重力に変換され 月ならどの高さまで跳べたか 可視化されます バーでリミットを選び バーの高さまで跳べるように 挑戦します Moon Jumperに 補正を加えました 視覚的な補正や ゲームプレイモードです テストを行い― バグのリストが 上がってきました まず私が iOSのバグに対処した後に セバスチャンが macOSのバグを担当します バグをすべて修正するまで Bashに行けません 2000人の前でやるなんて ワクワクしますね
まず1番目のバグは― “アニメーションが 仕様どおりに動かない” 迅速にデバッグするため シミュレータに切り替えます タップを検出する設定を したので― バーの高さまで跳びます バーまで跳ばないという バグを再現しましょう エディタのジャンプ関数へ Jump Barから移動し― ブレークポイントを 設定します タップでジャンプさせて デバッガで停止します まず上部のタブバーを 見てください Xcodeが“Debug”タブを 生成しました タブで作業したい方のために この動作が定義可能です (拍手) Xcodeメニューから 環境設定を開き “Behaviors”タブで 動作を設定します 多くの動作を 設定できますが― 今は 実行セクションの 一時停止の動作を設定します Xcodeがデバッガで 停止した際の動作です Debugタブが生成され― 実行が停止した時に 切り替わります タブ好きには うれしい設定ですね didReachSelectedHeightという 条件が見えます このプロパティの値を 確認しましょう デバッグコンソールに 切り替え― poでプロパティ値を見ると trueになっています タップ検出を設定すると trueになりますが― falseに変え バグを再現します コードを変えて falseに設定できますが― デバッグのためだけに コードを変えるのは避けたい そこでデバッガを使うのです expressionコマンドを 使います 例えば didReachSelectedHeight = false これの評価と実行が 行われると― プロパティが falseに変わりました “Step Over”ボタンで falseのブランチに進みます 再開すると 飛行士は バーに到達せず倒れます 一時停止して 式を入力せずに― タップするたびに これを再現したいのです そこでブレークポイントを 設定します 右クリックで “Edit Breakpoint”を選択 ポップオーバーで― ブレークポイントの動作を カスタマイズできます “Debugger Command”を選択 先ほど使った expressionコマンドを入力し― 自動で再開するよう設定 つまりブレークポイントが 式を実行させて プロパティの値を変え 自動的に再開させるのです 飛行士をタップするたび ジャンプに失敗し倒れます ここで修正すべきなのは? 倒れた後に 立ち上がらねばなりません 修正しましょう updateUIForJumpFailedという 関数に移動 UIKit Dynamicsで失敗を シミュレートしています まずUIDynamicAnimatorを 作成し 関数で動作を追加し 物理効果を作成 dynamicAnimatorDidPause デリゲートコールバックで 飛行士は向きを変え 中央に戻るはずです 下にスクロールすると― デリゲートコールバックが 実装されてます しかし ここは デリゲートが未設定です ここにコードを追加すれば 問題を修正できるでしょう 再コンパイルと再実行を行い 修正を検証しますが― このサイクルを ショートカットしたい そこでブレークポイントで 変更を挿入し 素早く便利に修正する方法を お見せします ブレークポイントを作るため ダブルクリックで― エディタウインドウを 開きます 再びDebugger Commandで 問題を修正するための コード行を入力します そして再開するよう設定 コードを変更しても 再コンパイルは まだです カスタムブレークポイントで 変更を挿入すると― 実行中のアプリケーションで テストできます タップすると ジャンプに失敗し倒れますが 立ち上がるので 修正は成功です もう1回 やりましょう (拍手) 再びメモを開きましょう 1番目のバグは修正したので チェックを入れます とてもいい気分ですね 次の3つは ゲームプレイモード関係です シミュレータで再生します バーより高く 10回 跳ぶという挑戦で バーの高さは 毎回 上がります
上部に“Score”ラベルが 表示されます まだ飛行士は ジャンプを失敗しますが― “Attempts”の回数が 増えません ラベルが変わらないという 2番目のバグです さらに ゲーム終了が 正常でないという問題と ラベルのレイアウトに 関する問題もあります 2番目のバグに戻り タップしましょう Attemptsラベルに ご注目を フラッシュしますが 変わりません アニメーションが遷移するので 値は設定されていますが― 不正な値なのです ラベルを変更するコードを 見つけて― ロジックを確認しましょう UILabelで テキストプロパティは変更 ブレークポイント ナビゲータに切り替えて 下のプラスボタンから ブレークポイントを選びます これらの選択肢の中から 私たちが使うのは― シンボリック ブレークポイントです 新しいブレークポイントの エディタが開くので “-”と この場合は入力します UIKitでは Objective-Cで記述します これを消すと ブレークポイントの下に― 行が追加されています UIKit Coreの1つの場所に 解決したという― フィードバックです 複数の場所になる場合も あります 1つもなければ― ブレークポイントが できなかったということです ここで もう一度 飛行士をタップすると― setTextでブレークポイントに 達します 表示はソースコードでなく アセンブリコードです システムフレームワークの アセンブリコードでも― 関数に渡された引数を 調べられます 呼び出し規約が分かれば レジスタを調べられるのです 私もレジスタを 覚えていませんが― デバッガが疑似レジスタを 提供してくれます $arg1が 第1引数を 保持するレジスタに変換され Objective-Cのレシーバが 表示されます “17フィート”と 表示されていますね この高さラベルのことです 私たちに必要ないので 他の引数を見ます ご存じの方もいるでしょうが 第2引数はセレクタです LLDBが暗黙的に認識しないため 表示されません 型変換して セレクタを 表示させる場合もあります 第3引数は メソッドに 渡されたパラメータです setTextに 渡された文字列なので アセンブリフレームで 引数を調べるのに好都合です でも目的のものでないので continueを押すと― ブレークポイントに達します $arg1でレシーバを調べると 高さラベルが “0フィート”になってます 問題が分かりました ジャンプすると同時に 高さラベルが更新され かなり頻繁に ブレークポイントに達します setTextのブレークポイントに 達するのは非常に困難です そこでシンボリック ブレークポイントを ジャンプ終了後だけに 設定してみましょう ナビゲータでインジケータを ダブルクリックすると エディタが開きます “Condition”に trueかfalseになる式を入れ trueの時だけ ブレークポイントを起動します もしプロパティが 分かっていれば― 式を編集して テストすることができます プロパティがないので 別の方法を見せます シンボリック ブレークポイントを消し jumpCompletedという関数で ブレークポイントを設定 アニメーション終了後に 関数が呼び出され UIとゲームの状態を更新します ここでやりたいのは― シンボリックブレークポイントの setTextへの設定です Debugger Commandを加えて “breakpoint set”続いて “one-shot true”と入力 これは一時的な ブレークポイントで 起動後 自動的に削除されます UILabel setTextという 名前を与えて 自動で再開するよう設定 これで jumpCompletedという関数の 実行が開始されると 一時的なブレークポイントが 設定され 再開します ブレークポイントには 実行開始後に達するのです 再開を押すと シミュレータでジャンプし setTextで ブレークポイントに達します それではpo $arg1で レシーバを調べましょう 別のUILabelインスタンスで 値は“0”です 上部のラベルの どちらかですね 目的のオブジェクトなので コードを確認しましょう スタックの次のフレームを 選択します ラベル値を 変更するコードです labelText変数を使い 現在は“0”ですね 上部で ラベルのテキストは 現在の値に設定されています 値のテキストは 新しい値を含む変数で― 誤字のようなので修正します valueTextに変えます
再コンパイルと再実行を行い テストする代わりに 実行中のアプリケーションで 変更をテストしましょう 現在の行の下に ブレークポイントを設定します ラベルを設定したままで― 正しい値に設定する行を 追加します カスタムブレークポイントで コードを挿入し 自動で再開するよう 設定します 再開を押すと コードの実行が再開され Attemptsラベルが 更新されました ありがとう (拍手) Scoreラベルでも 確認してみます こちらに戻りましょう 一時的なブレークポイントは もう不要なので消します didReachSelectedHeightは 変更しません タップすると うまくジャンプし どのラベルも更新されたので 修正成功です
バグにチェックを入れます 次のバグは ゲーム終了に関してです
10回の挑戦で ゲームは終わります 目的の状態を再現するため タップして待つ方法では― 時間がかかるうえに 何度も 繰り返す必要があります アニメーションを スキップする方法を― お見せしましょう updateUIForJumpSucceededに 移動します この関数は 色を変更した後に― jumpAstronaut(animated: true)を 呼び出します これをfalseにしましょう 今回も デバッグのために コードを変えるのは避けたいので 代わりにブレークポイントを この行に設定します コンソールの入力を消し タップすると この行で停止します falseに置き換えたいですが コンパイル済みなので― コードを置換できません そこで この行を実行せず スキップさせて expressionで 変更を挿入しましょう 行をスキップさせます 緑のラベルの“Thread 1”は 命令ポインタと呼ばれ 次に実行する命令の行を 示しています このアイコンをクリックしながら マウスを動かせば行を移動できます 停止中は変更できるので 下の行に動かしましょう 恐ろしげな警告が出ました 大いなる力には 責任が伴います 今日 ご紹介する中で 最もリスクが高い方法です アプリケーションへの 影響とは関係なく― ポインタを どこにでも動かせるからです 例えば 初期設定していない オブジェクトを示せば― メモリ管理の問題が生じます しかし上級者用の セッションなので 続けましょう
expressionコマンドを使い falseを呼び出します
再開を押して動かすと― アニメーションをスキップし ゲームの状態を更新
タップのたびに 実行されるように― ブレークポイントを 設定します まずは 行を1つスキップさせるので “thread jump”続いて“by 1”の コマンドを入力 これで現在のスレッドの コードを1行 飛ばします 次に式を呼び出すために― プラスボタンを押し コマンドを追加します jumpAstronaut (animated: false)です 自動再開も設定 そしてブレークポイントまで 実行されれば 実行前に ブレークポイントが起動 コマンドが実行され 1行 スキップ そして代わりの関数を expressionで呼び出します これで 飛行士をタップすると アニメーションをスキップし 簡単にバグが再現できます 10回の挑戦で終わるはずが かなり過ぎていますね ゲームの状態を 見てみましょう gamePlayというプロパティに あります ブレークポイントを設定し ジャンプすると プロパティの次の リファレンスで停止 poでオブジェクトの 現在の状態を出すと デバッグの記述が確認できます これはカスタム記述です poはプログラムの デバッグの記述を要求します これはカスタマイズ可能です ソースコードに切り替え 下までスクロールします CustomDebugStringConvertibleに GamePlayが拡張 debugDescriptionを実装し Stringを返しています デバッグのために どんなStringでも返せます Objective-Cオブジェクトでも 同様です p gamePlayコマンドと 比較します pはLLDBの代替コマンドで 組み込みフォーマッタを 使います 2種類の表示が出ました デフォルトフォーマッタは 完全修飾型名と― メモリアドレスと プロパティなどを表示 最大の挑戦回数は10で 正しい設定なので 論理エラーのようですね 挑戦回数が最大を超えても 判断できないのです 挑戦回数を変更するコードを 見つけましょう 変数ビューを開いて View Controllerを展開し 下のフィルタに gamePlayと入力します プロパティを展開し attemptsを選択 コンテキストメニューを開き Watch “attempts”を選択 ウォッチポイントが 生成されます ブレークポイント ナビゲータの下部に Watchpointsという名の グループとができます ウォッチポイントは― 変数の値が変更された時に 停止します 不要なブレークポイントを 消して 再開を押すと ウォッチポイントで停止 これが挑戦回数を 変更するコードです ウォッチポイントは 無効にします これらは挑戦回数と スコアを増やすコードです 最大回数を超えた時 終了させるロジックは― 見当たりません 材料は そろいましたが コードを変える前に― 私の仮説を試します ブレークポイントを作成し 問題を修正できるか 変更を挿入してみます Debugger Commandを加えて expressionを使用 最大回数を超えたら ゲーム状態は終了するよう設定し 自動再開も設定 問題が修正されるか 再開してテストします ブレークポイント後も続行し うまく修正されたようです 最初から検証します “Play Again”をクリックして 挑戦を10回させ ゲーム終了となったので 修正は成功です (拍手) コードに適用してください コピーして ブレークポイントを消し ペーストで挿入します 3番目をチェックして 残り1つは― ラベルのレイアウトです レイアウトを 任されたエンジニアたちは 左右の上端が 効率的な場所だと考えました しかしチームの判断で 差し戻されたので 新しいレイアウトを 試作しましょう グラフィック アプリケーションではなく コードで試作します 私は デバッガエンジニアなので 実行しながら デバッガを使います
ブレークポイントを ジャンプ関数に設定します ビューへのリファレンスを まず見つけましょう 入力をすべて消去し 新たにジャンプさせて ジャンプ関数で停止させます ビューのプロパティや アウトレットがなければ メモリアドレスが必要です それを見つけて ビューを操作する方法を― ご紹介します デバッグの記述には― カスタム記述が含まれます UIViewの デフォルトデバッグの記述に クラスとメモリアドレスが 含まれます デバッグの記述を得るのが 1つの方法ですが プロパティがあるので 簡単です View Controllerビューの 下のビューは? ビュー階層を見るには このボタンで― ビューデバッガを起動します 階層のスナップショットが 3Dになり ビューを調べられるのです 後でセバスチャンが話します 私が紹介するのは― デバッグコンソールで 単純な階層を見る方法です recursiveDescriptionという デバッグ関数を使います po self.view. recursiveDescriptionです うまくいかない場合は? この関数は デバッグのために存在するので― パブリックAPIではなく Swiftで使えません 定義されていない関数は Swiftで呼び出せないのです しかしObjective-Cは ダイナミックな言語で このような関数も 呼び出せます ではデバッガに Objective-Cの構文で― この式を評価させましょう “expression option -l objc”と 入力します フレームはSwiftでも コードはObjective-Cです
-Oを加え poと同様に デバッグの記述を確認します ダッシュ2つで オプションの終わりを示し あとはローインプットです Objective-Cフォーマットを 与えねばなりませんが― うまくいきません 一時的な式のコンテキストが 作成され― フレームの変数を 継承しないからです でも回避できます self.viewを バッククォートで囲むのです まず現フレームの コンテンツを評価し 結果を挿入すると 残りを評価してくれます (拍手) デバッグの記述が すべて表示されます ラベルをホストする ScoreboardViewの― メモリアドレスです ではpoとメモリアドレスを 使ってみましょう しかしSwiftは数字を ポインタとして扱わず うまくいきません そこで再び Objective-Cの登場です 同じことを 繰り返せばいいですが― ショートカットして 簡単なコマンドにしましょう エイリアスコマンドで pocコマンドを呼び出します pocでメモリアドレスから デバッグの記述を確認します メモリアドレスから 確認する方法を― もう1つ 紹介します 使うのは unsafeBitCastという関数です メモリアドレスを与え ScoreboardView.selfに 変更します unsafeBitCastでも 記述を確認できました unsafeBitCastは 型を返すので― .frameなどが使えます 今回は中央位置を調べて 修正しましょう 300に修正します 300に変更されましたね しかしシミュレータでは 変わっていません 停止中なので― 画面のフレームバッファに 変更が適用されないのです アニメーションを 変えるため― “expression CATransaction.flush”と入力
画面のフレームバッファが 更新されます (拍手) この2行で 新しい位置を修正して フラッシュを続けます とても便利なので 1つのコマンドにしました その方法をお見せします Pythonのファイルを開きます なぜPythonか? Pythonを使えばLLDB APIに フルアクセスできるからです Pythonで LLDBスクリプトを書き “nudge x-offset y-offset ”を入力 これで停止中にビューを ナッジできます 長いようですが ほとんどは停止の引数です 真ん中の重要な部分は 手動でやるはずだった 呼び出しです 時間がなく未完成ですが― ダウンロードして お使いいただけるようにします
スクリプトを 有効にする方法を見せます ホームディレクトリで .lldbinitと編集し command script importという行を 加えます 便利なエイリアスも追加 先ほどのpoc aliasや― トランザクションを フラッシュするエイリアスです
command script importを コピーして デバッグセッションで ペーストし 再開させます ここでナッジコマンドです “nudge” 水平位置が“0” 垂直方向が“-5” ビューのメモリアドレスも 入力し シミュレータで ナッジさせます (拍手) LLDBでは空白行で 改行すれば 前の行を繰り返すので ナッジに最適 右方向にナッジして 位置を調整します もう1つのビューも調整して Attemptsの位置を下げます また ナッジで一度 ビューの式を入力すると 記憶して 前に記述したのと 同じ式を適用します マシなレイアウトに なりました ナッジから提供された情報が あります 元の中央位置やフレーム値に 適用したオフセットなどです そこからレイアウトの コードなどを修正し 新しいレイアウトが 簡単にできました
では最後に… 先にバグを チェックしておきましょう 再コンパイルと再実行を 行う前に― 挿入した式を 消去せねばなりません 2回 実行するのを避けるためです 選択して Deleteキーで消すと早いです 以上が デバッグを迅速に 行うためのテクニックです 再コンパイルや 再実行をせずに― 私たちは4つのバグをすべて 診断できました 複雑なプロジェクトでは特に 時間を節約でき 再現が難しいバグの解決に 欠かせません このテクニックを ぜひ皆さんもお使いください (拍手) デバッグセッションで 取り上げた秘訣を 振り返ってみましょう まず Xcodeの“ビヘイビア”から デバッグタブを生成 LLDBのexpressionで プログラム状態を変更 自動再開するブレークポイントで 実行中にコードを挿入 “breakpoint set”続いて “one-shot true”を使って― 独立したブレークポイントを 作成 アセンブリフレームで― $arg1や$arg2などを使い 関数の引数を確認 命令ポインタかthread jumpで コードの行をスキップ ウォッチポイントで 変数の変更時に停止 Swiftフレームで Objective-Cを― expression -l objcで評価 デバッグ停止時に― CATransaction.flushで ビュー変更をフラッシュ カスタムLLDBコマンドの 追加については エイリアスコマンドで ショートカットを作成するか Pythonでコマンドを カスタマイズして作成 ナッジスクリプトを ウェブサイトに載せるので ご覧になって 活用してください
もう1つ お話ししたいのが LLDBのprintコマンドです おなじみのpoは デモで使いました デバッグの記述を要求し カスタマイズ可能でしたね poは“expression” “object-description”や “expression -O”の エイリアスです 一方 pコマンドは expressionのエイリアスです LLDBの 組み込みフォーマッタを使い オブジェクトを表します 知っておきたい3つ目のコマンドは frame variableです 他の2つと違い― コンパイルや 式の評価をしません 変数の値をメモリから 直接 読み取り LLDB組み込みフォーマッタを 使います コマンドの選択は 好みと目的の情報次第です でも覚えておいてください expressionコマンドも poやpも使えない時― フレーム内の変数を frame variableで調べられます
この後はセバスチャンが ビューデバッグの テクニックをご紹介します (拍手) ありがとう クリス
ビューデバッガを 活用する秘訣をお教えします また ダークモードの macOS Mojaveで 優れたデバッグが体験できるよう Xcode 10を改良しました デモでお見せしましょう デモ機に切り替えます クリスと同じ プロジェクトです バグが2つ 残っていましたね
私はMacの アプリケーションを使います Mac版のSolar Systemが ダークモードに映えますね バグを2つ 解決します 1つ目は“惑星の画像が 水平方向の中央にない” この地球の画像は確かに 右側にずれているので 問題に対処しましょう 2つ目は“ダークモードで ポップオーバーの字が読めない” 実際に ご覧ください このポップオーバーに 軌道の情報が表示されます 上部のラベルは 読みやすいですが― 下部は文字を選択しないと 読めません この2つに取り組みます さっそく始めましょう Xcodeで ビュー階層を取り込みます 問題と修正方法を見つけ ビールを楽しみましょう ただ Xcodeに切り替えると ポップオーバーが消えます バックグラウンドに 移るからです ビュー階層を取り込めません そこでアクティブ状態で 取り込む方法を― 2つ ご紹介しましょう ご覧のとおり ポップオーバーが消えます Touch Barを使うので Windowメニューから シミュレータを出します 再びポップオーバーを 開きましょう Touch Barの スプレー缶アイコンをタップすると Xcodeが提供するデバッグの オプションが表示されます Touch Barから 簡単にアクセス可能です Xcodeが バックグラウンド状態なので フルスクリーンモードで 開発中でも使えます オプションの1つで ビュー階層を取り込めますが Touch Barのない人には 別の方法があります
シミュレータを閉じ デバッグバーのボタンを Commandキーを押しながら クリックします アプリケーションを アクティブにせずに― マウスで クリックできる方法です これで ビュー階層の キャプチャを起動できます デバッガは アクティブ状態で停止 UIは描画を続け ポップオーバーも出てます 待機カーソルになるのは― アプリケーションが停止し マウスに反応しないからです
ビューデバッガでは ポップオーバーが見えません でも ちゃんと 取り込んでいるので 後でお見せします まず 画像ビューの レイアウトの問題です 画像ビューを少し拡大します 右側のインスペクタを見ると NSImageViewSimpleImageViewと なっています アンダースコアのついた プレフィックスなので― システムフレームワークの インターナルクラスです コードなどで画像ビューを 設定する際には使いません ビュー階層で オブジェクトを見ます Navigateメニューから “Reveal in Debug Navigator”へ 左側でスーパービューと サブビューに関連づけられています スーパービューは NSImageViewです そのスーパービューは PlanetGlobeViewで そのスーパービューは NSVisualEffectViewです
ImageViewを選べば― 右側の画像ビューの プロパティが確認できます レイアウトを調べましょう Auto Layoutを使ってるので その制約を― このボタンで表示できます レイアウトに影響する制約を すべて確認できます 例えば アスペクト比の制約などです また この縦の線は そろえの制約です 制約を選択すると右側に プロパティが表示されます 表示されている ワイヤフレームは― レイアウトに関与しているビューの コンテンツです コンテンツのないビューも あるので― この表示なのです 制約を選択したので インスペクタを見ましょう 画像ビューと惑星ビューの それぞれが 定数0で水平方向の中央で そろえられています だからスーパービューで そろうのです PlanetGlobeViewを ナビゲータで選択します 奇妙なことに 左側は大きいのに― 右側はそろっています 制約で水平方向で そろえていたはずなのに― 矛盾しています では惑星ビューの制約を見て 確認しましょう 前辺の制約を選択し インスペクタを見ます スーパービューで見た NSVisualEffectViewの前辺と 惑星ビューの前辺が そろえられています 定数30となっているので 納得できます 次は後辺の制約です
惑星ビューの後辺と スーパービューの後辺が 定数30でそろっています この制約は右側で 何も接しておらず 全体像がよくつかめません 現在 切り抜きされた コンテンツがないか― 確認しましょう このボタンで 切り抜きしたコンテンツを表示 すると惑星ビューが右方向へ 境界を越えて広がりました スーパービューでは 中央でそろっているので― 制約どおりです ただ ウインドウの境界を 越えています コードで制約を設定する時に うっかり2つを 入れ替えてしまいがちです 定数を間違えることも あります この場合はマイナス30を 30にしていました 修正して 定数を入れますが― 先ほどのクリスと同じく LLDBでやりましょう こちらの制約を選択します
そしてEditからコピーを選び 下にコンソール領域を 開きましょう このコピーによって ポインタがキャストされます Memory debuggerで 選択した場合も同様です コンソールで 非常に便利ですね (拍手) ありがとう デバッガ記述を出力し 定数がプラス30と確認します インスペクタで見ましたね マイナス30に設定しましょう expressionの省略である “e”を入力します そしてsetConstantを マイナス30に設定 しかし先ほどと同様 停止中は更新されません そこで CATransaction.flushを使い 停止したインターフェイスを 更新しましょう クリスが加えたコマンドを使います コマンドを入れましょう 惑星が水平方向の中央に 位置しました 定数を入れて成功です この変更を コードに適用しましょう
制約を選択すると 右側にバックトレースが表示され どのフレームが 割り当てられたか分かります 制約を作ったコードに ジャンプできるのです Malloc Stack Loggingを 有効にします ご覧に入れましょう 上部で“Edit Scheme”を 選択します “Diagnostics”タブの “Logging”で― Malloc Stackを Allocation and Free Historyに これでバックトレースが 生成されます Memory debuggerで 選択した場合も同様です スタックフレームに カーソルを重ねると フレームのフルネームが 見えます setupPlanetGlobeViewLayoutと なっています この矢印でコードの場所へ ジャンプできます ShiftキーとReturnキーと Optionキーを長押しすると このように別ウインドウに ファイルが開きます
制約のコード行が ハイライトされました 定数30を マイナス30に変更します 保存して閉じれば 最初のバグは終了です
いいですね 2つ目は― “ポップオーバーの字が 読めない”というバグです 見てみましょう
まず制約モードを 無効にして 切り抜きを消しましょう
コンソールの入力も消します 最初に アクティブ状態で 取り込む方法を見せました でもポップオーバーは 見えません ウインドウを1つしか 表示できないからです 他のウインドウも見ましょう ビュー階層を 上にスクロールすると 現在 見ているウインドウが 確認できます ルートレベルを折りたたむと 別のルートレベルが現れます ポップオーバーです macOSやiOSで 複数のウインドウがあれば 左側にルートレベルとして 表示されます 取り込むべきウインドウが 複数あるなら― 確認してください 3D表示で このように確認できます 読みづらくなっていますね ラベルを調べてみましょう ビューデバッガでは Commandキーを長押しすれば クリックスルーで 青のラベルを選択できます まずテキストの色です ダークモードに 映えるラベルを見つけて 問題を解決しましょう
テキスト色はRGBで 青になっています インスペクタには 色の名前も表示 アセットカタログの 色ということです Xcode 10では1つの色から バリエーションが生まれ 明るい色や暗い色があります ビューの外観によって いずれかの色に決まり インスペクタに表示されます 下の“View”セクションには “Appearance”と “Effective Appearance”があり Appearanceは 明示されてません これは よくあることで ほとんどのビューは― スーパービューなどから 外観を引き継ぎます しかしEffective Appearanceは “VibrantDark”で アセットカタログの色から 選ばれた色です インスペクタの下部には― デバッグの記述である 記述プロパティもあります 先ほどクリスが お見せしましたね poを使うことで― コンソールのデバッグの記述を 提供するだけではなく ビューデバッガからも 出せるのです
テキスト色に戻ります 2番目のラベルも よく見えますね システムが定めた labelColorとなっており アセットカタログの色では ありません システム色も 外観が変わると対応します 次は問題のラベルです 濃いダークグレーで 名前がありませんね つまりカスタム色で 外観の変化に対応しません それでは このテキスト色を システム色に変えましょう
このオブジェクトを 選択しながら eを入力して ポインタをキャスト setTextColor: と入力
トランザクションを フラッシュ ポップオーバーのフォントが 更新されました Storyboardファイルに 適用します ここで必ず全体を通して 外観が整っていることを 確認しましょう 複数のシステムの外観に 関わるからです その方法をお見せしましょう
システム全体の外観を 明るくして― ラベルを 確かめる必要はありません Xcode 10では 目的の対象だけ変えられます デバッグバーのボタンで “Light”を選択 アプリケーションの外観が 明るくなりました ポップオーバーを出して 読みやすさを確認 修正に成功しました 外観を変えて確認することは よくあるため― Touch Barにオプションを 追加しました 再びシミュレータで― ポップオーバーを開き ここのオプションを選択 修正オプションが出ました フルスクリーンモードでも アクセスできます コントラストを上げると アクセシビリティだけでなく 外観を明るく修正できます アプリケーションの見た目も 向上します もちろん システムの外観も同様です 問題は解決しましたね バグのリストに チェックを入れます デモを終了して スライドに戻りましょう (拍手) では おさらいです “Reveal”を使って― ビュー階層で現在の選択を 明らかにしました さらに 切り抜きを確認 Auto Layoutで 制約の問題を特定 選択されたオブジェクトを コピーして― オブジェクトポインタを使用 Malloc Stackを有効にして バックトレースを生成し― 制約に必要な変更を コードに適用 ビューデバッガのインスペクタで デバッグを記述 クリックスルーで 背後のビューを選択 ダークモードの デバッグでは― デバッグバーかTouch Barで 外観を修正 アクティブ状態で取り込み 最後に 名前と外観の情報を― ビューデバッガの インスペクタで確認 ダークモードの詳細は この2つのセッションの ビデオをご覧ください これでセッションは終了です ナッジスクリプトや その他の詳しい情報は ウェブサイトをご覧ください 今日の内容や デバッグについての質問は 明日9時からのラボで クリスや私がお答えします メモリデバッグについては 明日 iOSメモリの セッションがあります それではBashと WWDCをお楽しみください (拍手)
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。