iOS
LLDB
Swift

ビルドで待たないための、Simulator 上で実行中の view をいじる方法

More than 1 year has passed since last update.

Simulator ですでに動作している iOS アプリの view をちょっといじりたい時に便利な手段を紹介します。

手順

アプリを一時停止する

ます、メニューの Debug > Pause か、デバッグバーの Pause ボタンでアプリケーションを一時停止させます。

Debug < Pause ^⌘Y

Pause ボタンは、デバッグバーの左から3番目のボタンです

UIApplication が見えるスタックへ移動する

画面操作慣れしている方向け

Debug Navigator の Process View Display から、Thread 1 の main をクリックします。

スクリーンショット 2016-12-28 14.59.13.png

LLDBer 向け

main thread を選択

(lldb) thread list
Process 16234 stopped
* thread #1: tid = 0x5345c, 0x000000010b1b4f72 libsystem_kernel.dylib`mach_msg_trap + 10, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  thread #4: tid = 0x53536, 0x000000010b1bbefa libsystem_kernel.dylib`kevent_qos + 10, queue = 'com.apple.libdispatch-manager'
  thread #6: tid = 0x53538, 0x000000010b1b4f72 libsystem_kernel.dylib`mach_msg_trap + 10, name = 'com.apple.uikit.eventfetch-thread'

(lldb) thread select 1

main 関数の frame を選択

(lldb) thread backtrace
* thread #1: tid = 0x5345c, 0x000000010b1b4f72 libsystem_kernel.dylib`mach_msg_trap + 10, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x000000010b1b4f72 libsystem_kernel.dylib`mach_msg_trap + 10
    frame #1: 0x000000010b1b445e libsystem_kernel.dylib`mach_msg + 226
    frame #2: 0x0000000109e69ba4 CoreFoundation`__CFRunLoopServiceMachPort + 212
    frame #3: 0x0000000109e69021 CoreFoundation`__CFRunLoopRun + 1345
    frame #4: 0x0000000109e68884 CoreFoundation`CFRunLoopRunSpecific + 420
    frame #5: 0x000000010be19a6f GraphicsServices`GSEventRunModal + 161
    frame #6: 0x00000001076c1c68 UIKit`UIApplicationMain + 159
  * frame #7: 0x0000000106bf614f TableViewTraining`main + 111 at AppDelegate.swift:12
    frame #8: 0x000000010ae8f68d libdyld.dylib`start + 1
    frame #9: 0x000000010ae8f68d libdyld.dylib`start + 1

(lldb) frame select 7
frame #7: 0x0000000106bf614f TableViewTraining`main + 111 at AppDelegate.swift:12
   9    import UIKit
   10   
   11   @UIApplicationMain
-> 12   class AppDelegate: UIResponder, UIApplicationDelegate {
   13   
   14       var window: UIWindow?
   15 

View の一覧を確認する

Console から LLDB を実行する

デバッグコンソールから、Xcode に組み込まれているデバッガ LLDB を実行します。

dwx-dt-debugarea-1_2x.png

LLDB を使うと、コマンドラインから様々なデバッグ操作ができます。試しに help と入力すると、次のようにヘルプが表示されます:

(lldb) help
Debugger commands:

  apropos           -- List debugger commands related to a word or subject.
  breakpoint        -- Commands for operating on breakpoints (see 'help b' for
  ...

ここからは、LLDB の expression コマンドを使って、View の一覧を確認していきます。なお、-O も一緒に指定しますが、これは人間の読みやすい形式で表示するオプションです1

UIApplication は、アプリが起動している間存在するシングルトンなクラスです。このクラスのインスタンスから、現在表示されている View までたどることができます:

(lldb) expression -O -- UIApplication.shared
<UIApplication: 0x7f9772d00d40>

UIApplication は、現在有効な UIWindowUIApplication#keyWIndow に持っています:

(lldb) expression -O -- UIApplication.shared.keyWindow!
<UIWindow: 0x7f977660c400; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x6000000556c0>; layer = <UIWindowLayer: 0x6000002210e0>>

この UIWindow は、UIWindow#rootViewControllerViewController を持っています:

(lldb) expression -O -- UIApplication.shared.keyWindow!.rootViewController!
<UINavigationController: 0x7f9774031800>

この UIViewController#view から、UIView を入手できます:

(lldb) expression -O -- UIApplication.shared.keyWindow!.rootViewController!.view!
<UILayoutContainerView: 0x7f9772d09a30; frame = (0 0; 414 736); autoresize = W+H; gestureRecognizers = <NSArray: 0x600000056c80>; layer = <CALayer: 0x618000221060>>

さらに、この UIView の子孫 View を追いかけてみましょう。UIView は、recursiveDescription というデバッグ用のメソッドを備えています。ただ、Swift からは直接呼び出せないので、UIView の親クラスであるNSObject#value(forKey:) 経由で呼び出す必要があります:

(lldb) expression -O -- UIApplication.shared.keyWindow!.rootViewController!.view!.value(forKey: "recursiveDescription")!
<UILayoutContainerView: 0x7f9772d09a30; frame = (0 0; 414 736); autoresize = W+H; gestureRecognizers = <NSArray: 0x600000056c80>; layer = <CALayer: 0x618000221060>>
   | <UINavigationTransitionView: 0x7f9776607490; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x600000221b40>>
   |    | <UIViewControllerWrapperView: 0x7f9772f0b4a0; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x610000220c80>>
   |    |    | <UITableView: 0x7f9773007a00; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x6080000577c0>; layer = <CALayer: 0x608000222d20>; contentOffset: {0, -64}; contentSize: {414, 270}>
   |    |    |    | <UITableViewWrapperView: 0x7f9773007400; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x608000057af0>; layer = <CALayer: 0x608000222e00>; contentOffset: {0, 0}; contentSize: {414, 736}>
   |    |    |    |    | <TableViewTraining.MealTableViewCell: 0x7f977486b000; baseClass = UITableViewCell; frame = (0 180; 414 90); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x6000002215a0>>
   |    |    |    |    |    | <UITableViewCellContentView: 0x7f977660ca50; frame = (0 0; 414 89.6667); opaque = NO; gestureRecognizers = <NSArray: 0x600000058c00>; layer = <CALayer: 0x600000221ac0>>
   |    |    |    |    |    |    | <UIStackView: 0x7f9776609ab0; frame = (0 0; 414 89.6667); opaque = NO; autoresize = RM+BM; layer = <CATransformLayer: 0x600000221e60>>
   |    |    |    |    |    |    |    | <UIImageView: 0x7f97766056c0; frame = (0 0; 90 89.6667); clipsToBounds = YES; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x600000221c00>>
   |    |    |    |    |    |    |    | <UIStackView: 0x7f9776604dd0; frame = (100 0; 314 89.6667); opaque = NO; autoresize = RM+BM; layer = <CATransformLayer: 0x600000221ce0>>
   |    |    |    |    |    |    |    |    | <UILabel: 0x7f9776611b90; frame = (0 0; 314 20.3333); text = 'Kuniwak3'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x60000008f910>>
   |    |    |    |    |    |    |    |    | <UIView: 0x7f977660ceb0; frame = (0 30.3333; 314 59.3333); autoresize = RM+BM; layer = <CALayer: 0x6000002226a0>>
   |    |    |    |    |    |    |    |    |    | <TableViewTraining.RatingControl: 0x7f97766123f0; frame = (37 7.66667; 240 44); autoresize = RM+BM; layer = <CALayer: 0x600000222700>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f97766125b0; frame = (0 0; 44 44); opaque = NO; layer = <CALayer: 0x600000222a40>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9776614340; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000223b20>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f97766128b0; frame = (49 0; 44 44); opaque = NO; layer = <CALayer: 0x600000222b00>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9776614520; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000223c20>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9776612b70; frame = (98 0; 44 44); opaque = NO; layer = <CALayer: 0x600000222b60>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9776614700; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000223cc0>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9776612e30; frame = (147 0; 44 44); opaque = NO; layer = <CALayer: 0x600000222c00>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f97766148e0; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000223d60>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f97766130f0; frame = (196 0; 44 44); opaque = NO; layer = <CALayer: 0x600000222ca0>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9776614ac0; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000223e00>>
   |    |    |    |    |    | <_UITableViewCellSeparatorView: 0x7f97766133b0; frame = (15 89.5; 399 0.5); layer = <CALayer: 0x600000223000>>
   |    |    |    |    |    | <_UITableViewCellSeparatorView: 0x7f9776614060; frame = (20 89.6667; 394 0.333333); layer = <CALayer: 0x600000221b20>>
   |    |    |    |    | <TableViewTraining.MealTableViewCell: 0x7f977503ba00; baseClass = UITableViewCell; frame = (0 90; 414 90); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x610000220f60>>
   |    |    |    |    |    | <UITableViewCellContentView: 0x7f9772f08dc0; frame = (0 0; 414 89.6667); opaque = NO; gestureRecognizers = <NSArray: 0x60800005b3f0>; layer = <CALayer: 0x610000221fc0>>
   |    |    |    |    |    |    | <UIStackView: 0x7f9772f0f520; frame = (0 0; 414 89.6667); opaque = NO; autoresize = RM+BM; layer = <CATransformLayer: 0x610000221300>>
   |    |    |    |    |    |    |    | <UIImageView: 0x7f9772f0f6e0; frame = (0 0; 90 89.6667); clipsToBounds = YES; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x610000221000>>
   |    |    |    |    |    |    |    | <UIStackView: 0x7f9772f0f8c0; frame = (100 0; 314 89.6667); opaque = NO; autoresize = RM+BM; layer = <CATransformLayer: 0x610000221180>>
   |    |    |    |    |    |    |    |    | <UILabel: 0x7f9772f0fa80; frame = (0 0; 314 20.3333); text = 'Kuniwak2'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x61000008feb0>>
   |    |    |    |    |    |    |    |    | <UIView: 0x7f9772c10be0; frame = (0 30.3333; 314 59.3333); autoresize = RM+BM; layer = <CALayer: 0x608000225340>>
   |    |    |    |    |    |    |    |    |    | <TableViewTraining.RatingControl: 0x7f9772c12b00; frame = (37 7.66667; 240 44); autoresize = RM+BM; layer = <CALayer: 0x608000225280>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9772c12780; frame = (0 0; 44 44); opaque = NO; layer = <CALayer: 0x608000225240>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9772c15510; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x608000226600>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9772c12dc0; frame = (49 0; 44 44); opaque = NO; layer = <CALayer: 0x6080002253e0>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9772c159d0; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x608000226700>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9772c13080; frame = (98 0; 44 44); opaque = NO; layer = <CALayer: 0x608000225480>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9772c15bb0; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6080002267a0>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9772c13340; frame = (147 0; 44 44); opaque = NO; layer = <CALayer: 0x608000225520>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9772c15d90; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x608000226840>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9772c13600; frame = (196 0; 44 44); opaque = NO; layer = <CALayer: 0x6080002255c0>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9772c15f70; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6080002268e0>>
   |    |    |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772c13d20; frame = (15 89.5; 399 0.5); layer = <CALayer: 0x608000225920>>
   |    |    |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772c15230; frame = (20 89.6667; 394 0.333333); layer = <CALayer: 0x608000225260>>
   |    |    |    |    | <TableViewTraining.MealTableViewCell: 0x7f9774812a00; baseClass = UITableViewCell; frame = (0 0; 414 90); clipsToBounds = YES; autoresize = W; layer = <CALayer: 0x61800003fe60>>
   |    |    |    |    |    | <UITableViewCellContentView: 0x7f9772d02e20; frame = (0 0; 414 89.6667); opaque = NO; gestureRecognizers = <NSArray: 0x608000057070>; layer = <CALayer: 0x618000422700>>
   |    |    |    |    |    |    | <UIStackView: 0x7f9772d093a0; frame = (0 0; 414 89.6667); opaque = NO; autoresize = RM+BM; layer = <CATransformLayer: 0x618000422740>>
   |    |    |    |    |    |    |    | <UIImageView: 0x7f9772d0b760; frame = (0 0; 90 89.6667); clipsToBounds = YES; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x618000422760>>
   |    |    |    |    |    |    |    | <UIStackView: 0x7f9772d0c070; frame = (100 0; 314 89.6667); opaque = NO; autoresize = RM+BM; layer = <CATransformLayer: 0x618000422880>>
   |    |    |    |    |    |    |    |    | <UILabel: 0x7f9772d0c440; frame = (0 0; 314 20.3333); text = 'Kuniwak1'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x61800008d7f0>>
   |    |    |    |    |    |    |    |    | <UIView: 0x7f9772f0d630; frame = (0 30.3333; 314 59.3333); autoresize = RM+BM; layer = <CALayer: 0x610000220b00>>
   |    |    |    |    |    |    |    |    |    | <TableViewTraining.RatingControl: 0x7f9772f0d7d0; frame = (37 7.66667; 240 44); autoresize = RM+BM; layer = <CALayer: 0x6100002237c0>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9772c09280; frame = (0 0; 44 44); opaque = NO; layer = <CALayer: 0x608000222b20>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9772c10260; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x608000224460>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9772d0cbf0; frame = (49 0; 44 44); opaque = NO; layer = <CALayer: 0x618000422bc0>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9772c0fab0; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x608000224560>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9772d0d1c0; frame = (98 0; 44 44); opaque = NO; layer = <CALayer: 0x618000422a80>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9772c10440; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x608000224600>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9772d0d480; frame = (147 0; 44 44); opaque = NO; layer = <CALayer: 0x618000422ba0>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9772c10620; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6080002246a0>>
   |    |    |    |    |    |    |    |    |    |    | <UIButton: 0x7f9772d0d740; frame = (196 0; 44 44); opaque = NO; layer = <CALayer: 0x618000422c40>>
   |    |    |    |    |    |    |    |    |    |    |    | <UIImageView: 0x7f9772c10800; frame = (0 0; 44 44); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x608000224740>>
   |    |    |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772d0eb30; frame = (15 89.5; 399 0.5); layer = <CALayer: 0x618000422fc0>>
   |    |    |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772c0e7f0; frame = (20 89.6667; 394 0.333333); layer = <CALayer: 0x6080002235c0>>
   |    |    |    | <UIImageView: 0x7f9772f080b0; frame = (3 666.667; 408 2.33333); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x610000222580>>
   |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772f0a880; frame = (20 359.667; 394 0.333333); autoresize = W; layer = <CALayer: 0x610000220d00>>
   |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772f09d40; frame = (20 449.667; 394 0.333333); autoresize = W; layer = <CALayer: 0x610000220e40>>
   |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772f09610; frame = (20 539.667; 394 0.333333); autoresize = W; layer = <CALayer: 0x610000220f80>>
   |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772f0fd10; frame = (20 629.667; 394 0.333333); autoresize = W; layer = <CALayer: 0x610000221a80>>
   |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772f0fed0; frame = (20 719.667; 394 0.333333); autoresize = W; layer = <CALayer: 0x610000220ee0>>
   |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772f10190; frame = (20 809.667; 394 0.333333); autoresize = W; layer = <CALayer: 0x6100002216c0>>
   |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772f10350; frame = (20 899.667; 394 0.333333); autoresize = W; layer = <CALayer: 0x6100002213c0>>
   |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772f10510; frame = (20 989.667; 394 0.333333); autoresize = W; layer = <CALayer: 0x610000221e40>>
   |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772f106d0; frame = (20 1079.67; 394 0.333333); autoresize = W; layer = <CALayer: 0x6100002222a0>>
   |    |    |    | <_UITableViewCellSeparatorView: 0x7f9772f10890; frame = (20 1169.67; 394 0.333333); autoresize = W; layer = <CALayer: 0x610000222940>>
   |    |    |    | <UIImageView: 0x7f9772f0c940; frame = (408.667 405; 2.33333 264); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x610000221440>>
   | <UINavigationBar: 0x7f9772f08510; frame = (0 20; 414 44); opaque = NO; autoresize = W; gestureRecognizers = <NSArray: 0x6000000560e0>; layer = <CALayer: 0x610000220d40>>
   |    | <_UIBarBackground: 0x7f9772f0a670; frame = (0 -20; 414 64); userInteractionEnabled = NO; layer = <CALayer: 0x610000222aa0>>
   |    |    | <UIImageView: 0x7f9772f0ac70; frame = (0 64; 414 0.333333); userInteractionEnabled = NO; layer = <CALayer: 0x610000222100>>
   |    |    | <UIVisualEffectView: 0x7f9772f0ae50; frame = (0 0; 414 64); layer = <CALayer: 0x610000222b00>>
   |    |    |    | <_UIVisualEffectBackdropView: 0x7f977660a010; frame = (0 0; 414 64); autoresize = W+H; userInteractionEnabled = NO; layer = <UICABackdropLayer: 0x600000221ec0>>
   |    |    |    | <_UIVisualEffectFilterView: 0x7f9772d0a000; frame = (0 0; 414 64); autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x618000221080>>
   |    | <<UINavigationItemView: 0x7f9772f08be0; frame = (163 8; 88 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x610000220ba0>>: item=<<UINavigationItem: 0x6000001de5a0>: title:'Your Meals'> title=Your Meals>
   |    |    | <UILabel: 0x7f9772f09380; frame = (0 3; 88 21.3333); text = 'Your Meals'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x61000008dc50>>
   |    | <UINavigationButton: 0x7f9776608890; frame = (366 6; 39 30); opaque = NO; layer = <CALayer: 0x600000221340>>
   |    |    | <UIImageView: 0x7f9772f089d0; frame = (11 6.33333; 17 17); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x610000221fe0>>
   |    | <_UINavigationBarBackIndicatorView: 0x7f9772d0a5d0; frame = (12 11.6667; 13 21); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x618000422900>>

操作する UIView を入手する

先ほど入手した UIViewUIView#subviews から辿って行ってもよいですが、アドレスとクラスがわかっていれば、簡単にインスタンスを入手できます。

例えば、下の UIImageView インスタンスを操作したいとしましょう:

<UIImageView: 0x7f9772f0ac70; frame = (0 64; 414 0.333333); userInteractionEnabled = NO; layer = <CALayer: 0x610000222100>>

アドレスとは、0x7f9772f0ac70 の部分のことです。これとクラスを使うと、次のように unsafeBitCast(_:to:) を使ってインスタンスを取得できます:

(lldb) expression -O -- unsafeBitCast(0x7f9772f0ac70, to: UIImageView.self)
<UIImageView: 0x7f9772f0ac70; frame = (0 64; 414 0.333333); userInteractionEnabled = NO; layer = <CALayer: 0x610000222100>>

入手した UIView を料理する

ここまで出来れば、UIView をいかようにでも料理できます。

例えば、ある UIImageView の画像を消すには、次のようにします:

(lldb) expression -O -- unsafeBitCast(0x7f97766056c0, to: UIImageView.self).image = nil

(lldb) continue

Before

スクリーンショット 2016-12-28 16.44.21.png

After

スクリーンショット 2016-12-28 16.44.53.png

まとめ

Simulator で実行中の iOS アプリケーションの任意の UIView を操作する方法として、次の2つのコマンドを紹介しました。

(lldb) expression -O -- UIApplication.shared.keyWindow!.rootViewController!.view!.value(forKey: "recursiveDescription")!

(lldb) expression -O -- unsafeBitCast(0x7f9772f0ac70, to: UIImageView.self)

Enjoy, debugging!

参考文献


  1. expression -O -- hogepo hoge というエイリアスでも実行できます。