xcrun simctl addmediaは、写真・動画・連絡先(vCard形式)のファイルをシミュレータのライブラリに追加するサブコマンドである。

基本的な使い方

addmedia <device> <path> [... <path>]の形式で、ホスト側のファイルパスを指定して実行する。

$ xcrun simctl addmedia "TIL Media iPhone" ./til-photo.png

写真アプリのライブラリへ実際に取り込まれているかは、デバイスのデータディレクトリ配下のMedia/DCIM/100APPLE/を見ると確認できる。

$ find ~/Library/Developer/CoreSimulator/Devices/<UDID>/data/Media/DCIM -type f
.../DCIM/100APPLE/IMG_0001.JPG
.../DCIM/100APPLE/IMG_0002.JPG
...
.../DCIM/100APPLE/IMG_0007.PNG

新規作成したシミュレータには、addmediaを一度も実行していない状態でもサンプル写真が6枚(IMG_0001IMG_0006)あらかじめ入っている。 実際に写真アプリを起動して確認すると、追加した画像は「ライブラリ」タブに他の写真と並んで表示され、単にファイルを配置しただけでなく写真アプリの管理下に正しく取り込まれていることが分かる。 addmediaで追加したファイルは、それに続く連番のファイル名(この例ではIMG_0007.PNG)でコピーされる。 コピー後のファイルをチェックサムで比較すると、元のファイルとバイト単位で一致しており、単純にコピーされていることが分かる。

連絡先はvCard形式のファイルで追加できる

ヘルプに記載の通り、vCard形式(.vcf)のファイルを指定すると連絡先として追加できる。

$ cat til-contact.vcf
BEGIN:VCARD
VERSION:3.0
FN:TIL Taro
N:Taro;TIL;;;
TEL;TYPE=CELL:090-1234-5678
END:VCARD

$ xcrun simctl addmedia "TIL Media iPhone" ./til-contact.vcf

連絡先アプリのデータベース(Library/AddressBook/AddressBook.sqlitedb)を直接クエリすると、追加されたことを確認できる。

$ sqlite3 ~/Library/Developer/CoreSimulator/Devices/<UDID>/data/Library/AddressBook/AddressBook.sqlitedb \
    "SELECT First, Last FROM ABPerson;"
Kate|Bell
Daniel|Higgins
John|Appleseed
Anna|Haro
Hank|Zakroff
David|Taylor
TIL|Taro

写真と同様、新規シミュレータには最初から6件のサンプル連絡先が登録されている。

複数のファイルをまとめて指定できる

ヘルプに記載の通り、写真・動画・連絡先を混在させて複数ファイルを一度に指定できる。

$ xcrun simctl addmedia "TIL Media iPhone" ./til-photo.png ./til-contact2.vcf

上記を実行すると、写真ライブラリと連絡先の両方に同時に反映される。

未対応のファイル形式を指定するとエラーになる

.txtのような未対応の形式を指定すると、明確なエラーメッセージとともに失敗する。

$ xcrun simctl addmedia "TIL Media iPhone" ./til-notmedia.txt
Failed to import './til-notmedia.txt', error [NSPOSIXErrorDomain] 22: The operation couldn't be completed. File type unsupported.

An error was encountered processing the command (domain=com.apple.CoreSimulator.LaunchdSimError, code=133):
Multiple errors were returned; see stderr

存在しないファイルを指定するとsimctl自体がクラッシュする

一方、存在しないパスを指定した場合は、上記のような通常のエラーメッセージにはならず、simctlプロセス自体が未処理の例外でクラッシュする(終了コード134)。

$ xcrun simctl addmedia "TIL Media iPhone" ./nonexistent.jpg
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid domain=nil in -[NSError initWithDomain:code:userInfo:]'
*** First throw call stack:
(...)
libc++abi: terminating due to uncaught exception of type NSException

存在するが未対応の形式のファイルは正常にエラー処理されるのに対し、存在しないファイルは異なるコードパスを通ってクラッシュに至るとみられる。 スクリプトからaddmediaを呼ぶ場合は、実行前にファイルの存在を確認しておいた方が安全である。