Есть ли команда LLDB, которая может преобразовать необработанный адрес в пригодный для использования класс Swift?
Например:
(lldb) po 0x7df67c50 as MKPinAnnotationView
Я знаю, что этот адрес указывает на MKPinAnnotationView, но он не во фрейме, который я могу выбрать. Но я хочу преобразовать необработанный адрес в MKPinAnnotationView, чтобы я мог изучить его свойства. Это возможно?
(lldb)
моей консоли. Но без этого не вышло.expr -l Swift --
..Вы можете использовать
unsafeBitCast
функцию Swift для приведения адреса к экземпляру объекта:(lldb) e let $pin = unsafeBitCast(0x7df67c50, MKPinAnnotationView.self) (lldb) po $pin
Затем вы можете работать
$pin
как обычно - свойства доступа, методы вызова и т. Д.Ознакомьтесь с этой статьей для получения дополнительной информации: Swift Memory Dumping .
источник
(lldb) settings set target.language swift
. Кроме того, в некоторых случаях (например, при выходе за пределы модуля вашего приложения при приведении к типу из вашего приложения) вам может потребоваться выполнить это с помощьюe import MyApp
Формат lldb,
expression
похоже, изменился в Xcode 7.3. Следующее заставило меня начать:(lldb) expr -l Swift -- import UIKit (lldb) expr -l Swift -- let $view = unsafeBitCast(0x7fb75d8349c0, UIView.self)
источник
Для пользовательских классов вам необходимо импортировать свой проект
expr -l Swift -- import MyTestProject expr -l Swift -- let $vc = unsafeBitCast(0x7fad22c066d0, ViewController.self) expr -l Swift -- print($vc.view)
источник
Что касается Xcode 8 / Swift 3, вот что у меня сработало. (Это основано на ответе @sfaxon .)
(lldb) expr -l Swift -- import UIKit (lldb) expr -l Swift -- let $nav = unsafeBitCast(0x1030ff000, to: UINavigationController.self)
источник
Благодаря всем вышеперечисленным ответам unsafeBitCast также хорошо работает с приложением Xcode 8.3.2 / Swift 3 / macOS / Cocoa.
Запомните адрес текущего экземпляра
(lldb) p tabView.controlTint (NSControlTint) $R10 = defaultControlTint (lldb) p self (LearningStoryboard.NSTabViewController) $R11 = 0x00006080000e2280 { .....
Позже изучите их
(lldb) p unsafeBitCast(0x00006080000e2280, to: NSTabViewController.self).tabView.controlTint (NSControlTint) $R20 = graphiteControlTint (lldb) p $R11.tabView.controlTint (NSControlTint) $R21 = graphiteControlTint
Если что-то подобное случится
(lldb) p unsafeBitCast(0x00006080000e2280, to: NSTabViewController.self).tabView.controlTint error: use of undeclared identifier 'to' (lldb) p $R11.tabView.controlTint error: use of undeclared identifier '$R11'
убедитесь, что вы выбрали один из фреймов стека исходного кода Swift, а не ассемблер.
Это может произойти, когда приложение было приостановлено нажатием кнопки « Пауза» или остановлено с исключением. Выбрав соответствующий кадр стека, позвольте lldb вывести правильный язык программирования.
источник
Версия Objective-C
po ((MKPinAnnotationView *)0x7df67c50).alpha
источник
Debug View Hierarchy
представлении, щелкнул правой кнопкой мыши на представлении, а затем выбралPrint description of...
. Это дало мне адрес памяти и тип, который я мог вставить в приведенный выше код. Приятно знать, что визуальный отладчик помещает консоль в кадр Obj-C.Мне потребовалось больше времени, чтобы понять, что я хочу признать. Он похож на ответ @afinlayson, но с лучшим объяснением (надеюсь!) И фиксированным синтаксисом
Если вы хотите проверить свойства объектов с помощью отладчика иерархии представлений Xcode, то это будет работать: по умолчанию вы находитесь в контексте objc, поэтому вам придется переключить его в контекст Swift.
expr -l Swift -- import <YOUR PROJECT NAME>
expr -l Swift -- let $vc = unsafeBitCast(0x7fb7c51cb270, to: <YOUR PROJECT NAME>.<YOUR CUSTOM CLASS NAME>.self)
expr -l Swift -- print($vc.<PROPERTY NAME>)
Пример:
expr -l Swift -- import Football
expr -l Swift -- let $vc = unsafeBitCast(0x7fb7c51cb270, to: Football.Ball.self)
expr -l Swift -- print($vc.velocity)
источник
Ответ @Xi Chen отлично работает, когда ваш сеанс LLDB был запущен в контексте Swift. Однако в некоторых случаях вы могли остановиться в точке останова вне контекста Swift; например, когда это символическая точка останова для Objective-C API или когда находится в режиме иерархии представления отладки (по крайней мере, в Xcode 11.4).
error: unknown type name 'let' error: use of undeclared identifier 'unsafeBitCast'
В этом случае вам нужно будет сделать это по-старому, используя Objective-C:
e MKPinAnnotationView *$pin = (MKPinAnnotationView *)0x7df67c50
и теперь вы можете использовать,
$pin
как хотите.источник
po
является псевдонимом, что означает, что его можно переопределить. Вы можете переопределитьpo
, обработав шестнадцатеричные адреса с помощью objc:command regex po s/(0x[[:xdigit:]]+)/expression -l objc -O -- %1/ s/(.+)/expression -O -- %1/
Чтобы увидеть, какой эффект это имеет, вы можете указать lldb развернуть эти псевдонимы:
(lldb) settings set interpreter.expand-regex-aliases true
Также я создал https://github.com/kastiglione/swift_po , заменяющий
po
Swift. Он обрабатывает адреса объектов, а также имеет несколько других улучшений.источник
expression -l objc -O -- 0x76543210
это просто ответ для меня, и ему не нужно знать класс переменной из адреса!Самый простой способ, быстрый 4
expr unsafeBitCast(0x7df67c50, to: MKPinAnnotationView.self)
источник