LoginSignup
1

More than 5 years have passed since last update.

[XCode][iOS] sqliteのファイルパスを簡単に探すためのスクリプト

Last updated at Posted at 2016-07-31

環境

下記環境でiOS開発している。

  • XCode7

問題点

CoreDataでsqliteを利用したアプリ開発をしていると、シミュレーターで登録したデータの確認をするなどの目的で、sqliteのファイルを直接見たいことがある。

但し、sqliteのファイルパスが直感的ではないため探すのが面倒臭い。

ファイルパス

sqliteは、以下のディレクトリ構成で格納されるようだ。

sqliteのファイルパス
~/Library/Developer/CoreSimulator/Devices/[デバイス固有文字列]/data/Containers/Data/Application/[アプリケーション固有文字列]/Documents/[アプリケーション名].sqlite

上記パスの下記文字列がランダムな文字列になっている。

  • デバイス固有文字列
  • アプリケーション固有文字列

このうちデバイス固有文字列は、以下のファイルの中の「dict -> dict -> string」に定義されている。

DeviceID一覧が記載されているファイル
~/Library/Developer/CoreSimulator/Devices/device_set.plist

このファイルの中身は、以下のようになっている。

device_set.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>DefaultDevices</key>
    <dict>
        <key>com.apple.CoreSimulator.SimRuntime.iOS-8-0</key>
        <dict>
            <key>com.apple.CoreSimulator.SimDeviceType.Resizable-iPad</key>
            <string>英数字のランダム文字列がハイフン区切りで格納されている</string>
            <key>com.apple.CoreSimulator.SimDeviceType.Resizable-iPhone</key>
            <string>英数字のランダム文字列がハイフン区切りで格納されている</string>
             :
           <省略>

簡単にパスを取得する方法

ターミナルで以下のコマンドを実行すれば、sqliteのファイル一覧を日付更新順(降順)に出力できる。

% ls -t ~/Library/Developer/CoreSimulator/Devices/*/data/Containers/Data/Application/*/Documents/*.sqlite

sqliteのファイル名にアプリケーションの名称が入るため、開発しているアプリの数が少なければ、このコマンドを実行するだけで充分かもしれない。

ただし、同じアプリでも、複数のiOSのバージョンや複数のデバイスで動作確認をすると思うので、デバイス固有文字列と、

  • iOSバージョン(iOS-9-2, iOS-9-3,...)
  • モデル(iPhone-6s、iPad-Air,...)

の対応付けをしておくと便利だと思う。

そこで、device_set.plistを解析して、これらの一覧を表示できるスクリプトを作ってみた。

getXcodeAppliPath.rb
#! /usr/bin/env ruby

require 'rexml/document'

# File path : device_set.plist
DEVICE_SET_PLIST="#{Dir.home}/Library/Developer/CoreSimulator/Devices/device_set.plist"
SQLITE_LIST = "#{Dir.home}/Library/Developer/CoreSimulator/Devices/*/data/Containers/Data/Application/*/Documents/*.sqlite"

# Device information
class Device
  def initialize(os, model)
    @os = os
    @model = model
  end

  attr_reader :os, :model

  def to_s()
    sprintf("%s %s", os , model)
  end
end

# This class hold all device information of defined by device_set.plist
class DeviceHolder
  def initialize()
    @device = {}
  end

  def push(id, os, model)
    @device[id] = Device.new(os, model)
  end

  def get(id)
    @device[id]
  end

  def ids
    @device.key
  end

  def to_s(id)
    get(id).to_s
  end
end

class DeviceSetPlistReader
  def initialize(filename)
    @filename = filename
    @holder = DeviceHolder.new
  end

  def execute
    doc = REXML::Document.new(open(@filename))

    default_device = doc.root.elements['dict/dict']

    os_name = nil
    default_device.elements.each do |el|
      if 'key' == el.name
        os_name = trimming(el.text)
      elsif 'dict' == el.name
        read_device_id(el, os_name)
      end
    end

    @holder
  end

  private

  def trimming(text)
    text.split('.').last
  end

  def read_device_id(target, os_name)
    # Ex.
    #   <key>com.apple.CoreSimulator.SimDeviceType.Resizable-iPad</key>
    #   <string>DEVICE_ID1</string>
    #   <key>com.apple.CoreSimulator.SimDeviceType.Resizable-iPhone</key>
    #   <string>DEVICE_ID2</string>
    model = nil
    target.elements.each do |el|
      if 'key' == el.name
        model = trimming(el.text)
      elsif 'string' == el.name
        @holder.push(el.text, os_name, model)
      end
    end
  end
end

#### Start process

reader = DeviceSetPlistReader.new(DEVICE_SET_PLIST)
holder = reader.execute

Dir.glob(SQLITE_LIST).sort{|x,y| -1*(File::stat(x) <=> File::stat(y))}.each do |file|
  dirs = file.split('/')
  device_id = dirs[-8] # Device ID is in the 8th from behind.
  application_name = dirs[-1].sub(/.sqlite$/, '')
  printf("%s\n  %s\n    %s\n", application_name, holder.to_s(device_id), file)
end

実行すると以下のようになる。

% ruby getXcodeAppliPath.rb
DummyAppli
  iOS-9-3 iPhone-6s
    /Users/hoge/Library/Developer/CoreSimulator/Devices/XXXX-XXXX-XXXX/data/Containers/Data/Application/XXXX-XXXX-XXXX/Documents/DummyAppli.sqlite
DummyAppli
  iOS-9-2 iPhone-6s
    /Users/hoge/Library/Developer/CoreSimulator/Devices/XXXX-XXXX-XXXX/data/Containers/Data/Application/XXXX-XXXX-XXXX/Documents/DummyAppli.sqlite

さいごに

ググると、アプリケーションのパスを表示してくれるソフトは、有料だといくつかあるらしい(ex. SimPholdersとか)。
こういうアプリだとメニューバーに常駐させてグラフィカルに操作できたりするので便利そうだ。

Scala版も作成してみました。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1