Swiftで[self.view recursiveDescription]を使用する方法はありますか?この方法を使用しようとしていますが、次のエラーが発生します。
'UIView' does not have a member named 'recursiveDescription'
助言がありますか?
Swift)からプライベート/ドキュメント化されていないObjective-C API(UIView
の-recursiveDescription
メソッドなど)にアクセスするには、次のようにします。
UIView
)。カテゴリヘッダーでプライベートメソッドを宣言します。
// UIView+Debugging.h
@interface UIView (Debugging)
- (id)recursiveDescription;
@end
これで、ブレークポイントを設定し、LLDBに再帰的な説明を出力できます。
po view.recursiveDescription() as NSString
Lldbでビュー階層を表示する場合は、カテゴリやブリッジヘッダーなどを追加する必要はありません。 Objective-Cコードをデバッグする場合、通常、(lldb)
プロンプトで次のコマンドを使用します。
po [[UIWindow keyWindow] recursiveDescription]
ただし、Swiftフレームで一時停止している場合、lldbはSwift式を予期することがあります。ただし、expr
(po
省略形実際にはexpression
)を呼び出しています)
expr -l objc++ -O -- [[UIWindow keyWindow] recursiveDescription]
IOS 8でビューコントローラーの階層を表示すると、次のように同じパターンが発生します。
po [UIViewController _printHierarchy]
または、Swift frame:
expr -l objc++ -O -- [UIViewController _printHierarchy]
WWDC 2018 Xcodeを使用した高度なデバッグ では、次の行を含むテキストファイル~/.lldbinit
を作成して、エイリアスexpr
を定義することにより、この複雑なpoc
構文から離れることを提案しています。
command alias poc expression -l objc -O --
その後、次のようなことができます:
poc [UIViewController _printHierarchy]
Xcode 8がビューデバッガーを導入したことは注目に値します(クリック )は、ビュー階層を分析するよりインタラクティブな方法を提供し、ビュー階層のLLDB recursiveDescription
の必要性をほとんど排除します。詳細については、WWDC 2016ビデオ Xcodeによるビジュアルデバッグ を参照してください。確かに、上に示したrecursiveDescription
手法にフォールバックしなければならないこともありますが、ほとんどの場合、ビューデバッガーはこれをはるかに自然で直感的なプロセスにします。
Xcode 9では、このビューデバッガーが拡張され、関連するビューコントローラーも含まれるようになりました。
Swift 2.0では、次のように実行できます:
_po view.performSelector("recursiveDescription")
_
(iOS10 Beta3でテスト済み)Swift 3.0では、これは少し複雑です:
po let s = view.perform("recursiveDescription"); print(s)
po view.value(forKey: "recursiveDescription")!
最初にカテゴリを追加します@interface
なし@implementation
ブリッジヘッダー内。
@interface UIView (Debug)
- (id)recursiveDescription;
- (id)_autolayoutTrace; // This one is even sweeter
@end
次に、コンソールで
po self.recursiveDescription() as NSString
po self._autolayoutTrace() as NSString
ここでの鍵はas NSString
ないas String
expression -l objc -O -- [`self.view` recursiveDescription]
UIKitはObjective-Cフレームワークにあるため、Objective-C形式で入力する必要があります。
再帰的記述は、デバッグ目的でのみ存在します。これはパブリックAPIの一部ではないため、Swiftでは使用できません
また、Swiftは厳密な言語であり、厳密に定義されていない関数を呼び出すことはできません。
Objective-C、これは動的言語なので、このような関数を呼び出すことができます。
したがって、Objective-C構文でこの式を評価するようにデバッガーに指示する必要があります
そしてそれを行う方法は、オプション-l objcで式を使用することです
-O、poと同じようにデバッグの説明も必要であることをデバッガーに通知します-これ以上オプションがないことを示します。
Put [self.view]ビューをバックティックに配置する必要があります。
[`self.view`]
バックティックは、最初に現在のフレームでこれの内容を評価し、結果を挿入してから、残りを評価することができる前処理ステップのようなものです。
私の答えは、Xcodeとlldbを使用したWWDC 2018 Session 412の高度なデバッグからのものです。
そのメソッドを使用して、UIViewのカテゴリの宣言をブリッジヘッダーに追加します。
@ Rob Mayoff'sanswer に基づいて構築:
extension UIView {
/**
Wrapper for useful debugging description of view hierarchy
*/
var recursiveDescription: NSString {
return value(forKey: "recursiveDescription") as! NSString
}
}