xcrun simctl listappsは、シミュレータにインストール済みのアプリの一覧を、各アプリの詳細情報付きで表示するサブコマンドである。
基本的な使い方
listapps <device>の形式で実行する。
$ xcrun simctl listapps "TIL ListApps iPhone"
{
"com.apple.Bridge" = {
ApplicationType = System;
Bundle = "file:///Library/Developer/CoreSimulator/Volumes/.../Bridge.app/";
CFBundleDisplayName = Watch;
CFBundleIdentifier = "com.apple.Bridge";
DataContainer = "file:///Users/xxx/Library/Developer/CoreSimulator/Devices/<UDID>/data/Containers/Data/Application/<UUID>/";
IsRemovable = 0;
...
};
...
}
出力は波かっこと;区切りの、Objective-Cの古い形式のプロパティリスト(NSDictionaryのdescription形式)である。
見た目はJSONに似ているが、キーを引用符で囲まない・区切りは;・末尾カンマなしなど文法が異なり、そのままjqなどのJSONパーサーには通せない。
SystemとUserでアプリの種類を区別できる
ApplicationTypeフィールドで、プリインストール済みのシステムアプリか、後からinstallしたユーザーアプリかを区別できる。
新規作成したシミュレータの時点では、36個のシステムアプリだけが登録されており、いずれもApplicationType = Systemである。
ここにsimctl installでアプリを追加すると、ApplicationType = Userのエントリが増える。
$ xcrun simctl listapps "TIL ListApps iPhone" | grep -A10 '"com.til.fakeapp"'
"com.til.fakeapp" = {
ApplicationType = User;
Bundle = "file:///Users/xxx/.../Containers/Bundle/Application/<UUID>/TILFakeApp.app/";
BundleContainer = "file:///Users/xxx/.../Containers/Bundle/Application/<UUID>/";
CFBundleIdentifier = "com.til.fakeapp";
DataContainer = "file:///Users/xxx/.../Containers/Data/Application/<UUID>/";
IsDeveloperApp = 1;
IsFirstParty = 0;
IsRemovable = 1;
...
};
システムアプリはBundleと実行ファイルの実体がランタイムの読み取り専用ボリューム上にあるのに対し、ユーザーアプリはBundleContainer・DataContainerともにデバイスのデータディレクトリ配下に作成され、IsDeveloperApp・IsRemovableも1になる。
uninstallすると、対応するエントリは一覧から即座に消える。
CFBundleDisplayNameはローカライズ文字列で上書きされる場合がある
アプリのInfo.plistのCFBundleDisplayNameを書き換えても、.lprojフォルダ配下のInfoPlist.stringsに同名のローカライズ済み文字列が残っていると、listappsにはそちらの値が表示される。
$ plutil -p ./TILFakeApp.app/Info.plist | grep CFBundleDisplayName
"CFBundleDisplayName" => "TIL Fake App"
$ plutil -p ./TILFakeApp.app/en.lproj/InfoPlist.strings | grep CFBundleDisplayName
"CFBundleDisplayName" => "Preview"
$ xcrun simctl listapps "TIL ListApps iPhone" | grep -A3 '"com.til.fakeapp"'
"com.til.fakeapp" = {
ApplicationType = User;
Bundle = "file:///...TILFakeApp.app/";
CFBundleDisplayName = Preview;
既存アプリを複製してbundle identifierだけ差し替えるような検証をする場合は、Info.plistだけでなく各.lprojのInfoPlist.stringsも合わせて書き換えないと、意図した表示名にならないので注意する。
listappsに表示されないアプリも存在する
listappsは、シミュレータのランタイムに含まれる.appのうち一部だけを表示しており、すべての.appを網羅しているわけではない。
たとえばAccountAuthenticationDialog.appのような内部サービス用アプリを、bundle identifierだけ差し替えてcom.til.hiddenappとしてsimctl installでインストールすると、simctl launchで実際に起動できるにもかかわらずlistappsの一覧には表示されない。
$ xcrun simctl launch "TIL ListApps iPhone" com.til.hiddenapp
com.til.hiddenapp: 60557
$ xcrun simctl listapps "TIL ListApps iPhone" | grep -c "com.til.hiddenapp"
0
get_app_containerでも同様に、com.til.hiddenappのコンテナは取得できない。
listappsの一覧は「ユーザーが目にする可能性のあるアプリ」を対象にしたものであり、内部サービス用のアプリまでは対象にしていないとみられる。
