この記事はGunosy Advent Calendar 2017の16日目の記事です。
昨日は@yamarkzさんの【ビットコイン】ウォレットの概要とHDウォレットの仕組みでした。

こんにちは。グノシー開発部iOS担当の@hongmhoonです。

今日はiPhoneのホーム画面であるSpringBoardをデバッグしてみたいと思います。
もちろん実機iPhoneは普通ではデバッグ出来ないので実機ではなくiPhoneのシミュレータで行います。

Xcodeとシミュレータ準備

ここでは現在(2017年12月)の最新版のXcode9.2とiPhone X(iOS11.2)を利用します。
念のためXcodeとシミュレータは両方とも一度終了してから新しく起動します。
開くプロジェクトは既存でも新規でも構いません。

スクリーンショット 2017-12-12 22.00.19.png

始める前に起動デバイスがiPhone Xになっていることを確認します。

スクリーンショット 2017-12-12 22.00.56.png

プロセスにアタッチ

通常の開発では大体Run[Cmd + R]コマンドでアプリを実行してデバッグしていると思いますが、SpringBoardは既に実行中なので
Debug -> Attatch to Process -> SpringBoardを選択してSpringBoardプロセスにアタッチします。

スクリーンショット 2017-12-12 22.01.29.png

しばらく待ってデバッグバーにこのようにSpringBoardと表示されるのを確認します。
これでSpringBoardプロセスに無事アタッチできました。

スクリーンショット 2017-12-12 22.02.06.png

デバッグ開始

デバッグのためにプロセスを一時停止する方法は色々ありますが、
今回はメニューからDebug -> View Debugging -> Capture View Hierachyを選択するようにします。

スクリーンショット 2017-12-12 22.08.11.png

しばらく待つとなんかそれっぽい画面が現れます。左側を見るとWindowが4つもあるのがわかります。

スクリーンショット 2017-12-12 22.09.16.png

左側から各Windowをクリックしながら確認するとホーム画面のアイコンはSBHomeScreenWindowで表示されているのがわかります。

スクリーンショット 2017-12-12 22.12.18.png

もうちょっと触ってみるとSBIconControllerでアイコンの情報があるのがわかりましたのでSBIconControllerの情報を出力してみます。
今回はコンテキストメニューからPrint Description of SBIconController選択します。

スクリーンショット 2017-12-12 22.19.45.png

出力結果を見て見るとvisibleIconIdentifiersに色々なアプリのIdentifierが見えます。Mapsmobilesafariなどだいたいはそのままどんなアプリか推測できます。
com.apple.Bridgeなどのパッと見わからないアプリは、こちらwhat-is-the-bundle-identifier-of-apples-default-applications-in-iosからWatchアプリであることがわかります。

Printing description of $32:
<SBIconController: 0x7ff896803600; orientation: UIInterfaceOrientationPortrait; isEditing: NO; model: <SBIconModel: 0x600002ad4190; store: <SBDefaultIconModelStore: 0x60000023caa0>; applicationDataSource: 0x7ff896803600; rootFolder: <SBRootFolderWithDock: 0x60400011a550, (null)>; visibleIconIdentifiers: {(
    "com.apple.Maps",
    "com.apple.mobilesafari",
    "com.apple.DocumentsApp",
    "com.apple.Health",
    "com.apple.Bridge",
    "com.apple.reminders",
    "com.apple.Preferences",
    "com.apple.news",
    "com.apple.Passbook",
    "com.apple.mobileslideshow",
    "com.apple.MobileAddressBook",
    "com.apple.MobileSMS",
    "com.apple.mobilecal"
)}; ignoresIconsNotInIconState: NO; sortsIconsAlphabetically: NO>; rootFolderController: <SBRootFolderController: 0x7ff89a021000; folder: <SBRootFolderWithDock: 0x60400011a550, (null)>; folderView: <SBRootFolderView: 0x7ff89a045a00; folder: <SBRootFolderWithDock: 0x60400011a550, (null)>; editing: NO; scrolling: NO; orientation: UIInterfaceOrientationPortrait; currentPageIndex: 1; iconListViewCount: 2; statusBarHeight: 44.000000; isScalingViewBorrowed: NO; minusPageCount: 1; dockOffscreenProgressSettingClients: NSHashTable {
}
; pageState: icon>>>

オブジェクト調査開始

せっかくなのでSBIconControllerのアドレス0x7ff896803600から利用可能なオブジェクトのメソッドをすべて表示して見ます。
po [0x7ff896803600 _shortMethodDescription]と入力して見ます。
*アドレス0x7ff896803600は環境によって変わるので試す場合は自分の出力からの値を利用してください。

参考:iOSデバッグ時に有用なメソッド

(lldb) po [0x7ff896803600 _shortMethodDescription]
<SBIconController: 0x7ff896803600>:
in SBIconController:
    Class Methods:
        + (BOOL) _supportsPopovers; (0x101e70012)
        + (id) sharedInstance; (0x101e6229c)
        + (id) sharedInstanceIfExists; (0x101e62360)
    Properties:
        @property (readonly, nonatomic) BOOL canOpenFolders;
        @property (readonly, nonatomic) BOOL canCloseFolders;
        @property (retain, nonatomic) _UILegibilitySettings* legibilitySettings;
        @property (nonatomic) BOOL hasRestrictedEnforcedLayout;  (@synthesize hasRestrictedEnforcedLayout = _hasRestrictedEnforcedLayout;)
        @property (nonatomic, getter=isUninstallingSystemAppsRestricted) BOOL uninstallingSystemAppsRestricted;  (@synthesize uninstallingSystemAppsRestricted = _uninstallingSystemAppsRestricted;)
        @property (retain, nonatomic) SBIconView* highlightedIconView;  (@synthesize highlightedIconView = _highlightedIconView;)

...省略...

        @property (readonly) unsigned long hash;
        @property (readonly) Class superclass;
        @property (readonly, copy) NSString* description;
        @property (readonly, copy) NSString* debugDescription;
    Instance Methods:
        - (id) nestingViewController:(id)arg1 animationControllerForOperation:(long)arg2 onViewController:(id)arg3 animated:(BOOL)arg4; (0x101e73b40)
        - (id) nestingViewController:(id)arg1 interactionControllerForAnimationController:(id)arg2; (0x101e7427e)
        - (void) nestingViewController:(id)arg1 willPerformOperation:(long)arg2 onViewController:(id)arg3 withTransitionCoordinator:(id)arg4; (0x101e745c1)
        - (void) handleReachabilityModeActivated; (0x101e7674a)
        - (void) handleReachabilityModeDeactivated; (0x101e767ed)

...省略...

メソッド呼出

これでView Hierachyからオブジェクトの変数やメソッドを探せるようになりましたので簡単なメソッド呼出をして見たいと思います。
アイコンのフォルダ名を狙って見ます。
色々クリックしてみるとアイコンのフォルダ名のビューはSBFolderTitleTextFieldであることがわかりましたので先ほどと同じくコンテキストメニューからPrint Description of SBFolderTitleTextField選択してみます。

スクリーンショット 2017-12-12 22.39.44.png

出力結果を見て見るとSBFolderTitleTextFieldUITextFieldのサブクラスでした。

Printing description of $92:
<SBFolderTitleTextField: 0x7ff89618f000; baseClass = UITextField; frame = (43 89; 288.667 56); text = 'Extras'; opaque = NO; gestureRecognizers = <NSArray: 0x60400084ea60>; layer = <CALayer: 0x604000829e40>>

ならsetText:でフォルダ名を変更出来そうな気がするのでして見ます。
変更後反映のためにcontinueでプロセスを再開します。

(lldb) po [0x7ff89618f000 setText:@"hmhv"]
0x000000010e60acc0

(lldb) continue
Process 5812 resuming

お!予想通りフォルダ名が変更されました!!
*フォルダ名を再表示させると元に戻ります。

スクリーンショット 2017-12-12 22.43.51.png

まとめ

今日はiPhoneのホーム画面であるSpringBoardをデバッグしてみました。この方法で同じくマップやsafariなどのお馴染みのアプリもデバッグが可能なので色々試して見てください。
ちなみに今まで使っていたデバッグコマンドの poってなんの略かわかりますか?
print objectでしょうというそこのあなた、正解は以下のコマンドで自分で確認して見てください。

(lldb) help po
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.