UIVIews に関連する可能性のある問題をデバッグする一環として、LLDB から実行する Python スクリプトを作成したいと考えています。状態を比較できるように、ブレークポイント内のビューとすべてのビューの子のすべての設定を抽出することを考えていました。このトピックに関する WWDC ビデオをチェックしてから、時間をかけて lldb.llvm.org/scripting.html を読みましたが、あまり役に立ちませんでした。例をウェブで検索しても、それらと実質的に異なるものは何も見つかりませんでした。
私の問題は、ブレークポイントで iOS 変数にアクセスする方法を見つけようとしていることです。私が見た例では、数値の変換やシェル コマンドの模倣などを行っています。興味深いものですが、私の目的には役に立ちません。「スクリプトのヘルプ(lldb.SBValue)」などでヘルプ情報を読んでいるのですが、結果が膨大で使用パターンが不明なため、処理が遅いです。いくつかの iOS オブジェクトをトラバースする方法の 1 つの適切な例は、システムを理解するのに役立つと思います。誰かが知っているか、コードのスニペットを共有できますか?
アップデート:
これを書いたのは、UIView の使用におけるバグを追跡するのに役立つためです。ビューツリー全体を表示できるかどうかを確認するために、これを改良するためにもう少し作業を行いたいのですが、これで問題を解決するのに十分だったので、他の人の時間を節約するためにここに置きます.
import lldb
max_depth = 6
filters = {'_view':'UIView *', '_layer':'CALayer *', '_viewFlags':'struct'}
def print_value(var, depth, prefix):
""" print values and recurse """
global max_depth
local_depth = max_depth - depth
pad = ' ' * local_depth
name = var.GetName()
typ = str(var.GetType()).split('\n')[0].split('{')[0].split(':')[0].strip()
found = name in filters.keys() # only visit filter items children
if found:
found = (filters.get(name) == typ)
value = var.GetValue()
if value is None or str(value) == '0x00000000':
value = ''
else:
value = ' Val: %s' % value
if var.GetNumChildren() == 0 and var.IsInScope():
path = lldb.SBStream()
var.GetExpressionPath(path)
path = ' pathData: %s' % path.GetData()
else:
path = ''
print '^' * local_depth, prefix, ' Adr:', var.GetAddress(), ' Name:', name, ' Type:', typ, value, path
if var.GetNumChildren() > 0:
if local_depth < 2 or found:
print pad, var.GetNumChildren(), 'children, to depth', local_depth + 1
counter = 0
for subvar in var:
subprefix = '%d/%d' % (counter, var.GetNumChildren())
print_value(subvar, depth - 1, subprefix)
counter += 1
def printvh (debugger, command_line, result, dict):
""" print view hierarchy """
global max_depth
args = command_line.split()
if len(args) > 0:
var = lldb.frame.FindVariable(args[0])
depth = max_depth
if len(args) > 1:
depth = int(args[1])
max_depth = depth
print_value(var, depth, 'ROOT')
else:
print 'pass a variable name and optional depth'
そして、以下を .lldbinit に追加しました:
script import os, sys
# So that files in my dir takes precedence.
script sys.path[:0] = [os.path.expanduser("~/lldbpy")]
script import views
command script add -f views.printvh printvh
LLDB プロンプトで「printvh self 3」と入力するだけです。