7
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

macrubyでのSandbox有効アプリの開発について

Last updated at Posted at 2013-04-29

macrubyでSandboxのsecurity-scoped bookmarkを取り扱う方法

Mac App Storeに申請するアプリはすべてSandboxが有効でなければならない。Sandboxを有効化する上で必要な初期設定は開発言語に関係なく、TARGETS > Summary > Entitlements > Enable App Sandboxingにチェックを入れて、必要なAccessにチェックを入れておく必要がある。Sandboxの設定ではインターネットアクセスや印刷などいくつかの処理に対して可否を設定することにになるが、ここではファイルへのアクセスについてまとめる。

Sandboxが有効なアプリでは、アプリが勝手にファイルを新規保存したり読み込んだりすることができない。ただし、Entitlementsの
com.apple.security.files.user-selected.read-write
をYESにしておくとユーザーがNSOpenPanelやNSSavePanelを介して選択したファイルやフォルダへのアクセスが可能になる。しかしこれだけでは不便なので、ユーザーが選択したファイルに後ほどアクセスするための設定
com.apple.security.files.bookmarks.app-scope
がある。これを有効にしておくと、NSOpenPanelやNSSavePanelで指定したファイルを「bookmarkデータ(security-scoped bookmarks)」として格納することができる(NSData)。さらにBookmarkデータはplistに保存しておくことができるので、次回起動時に自動で読み込んだりすることができる(user-selectedを有効にするだけではできない)。なお、com.apple.security.files.bookmarks.app-scopeについてはxcodeのGUI上にチェックボックスがないようなので、Entitlementsを直接編集して、上記Keyを追加、TypeをBoolean、ValueをYESにしておく必要がある。具体的な手順について以下まとめる。

NSOpenPanelでopenPanel = NSOpenPanel.openPanelを開き、ファイルを読み込んだ後、

bookmarkData.rb
def bkURLtoData(url)
    error = Pointer.new('@')
    bkFileData = url.bookmarkDataWithOptions(NSURLBookmarkCreationWithSecurityScope,
                                                 includingResourceValuesForKeys:nil,
                                                 relativeToURL:nil, error:error)
    if error[0]
        puts error[0].description
        raise
    end
    return bkFileData
end
    
def bkDataToURL(data)
    error = Pointer.new('@')
    bkFileURL = NSURL.URLByResolvingBookmarkData(data,
                                                     options:NSURLBookmarkResolutionWithSecurityScope,
                                                     relativeToURL:nil,
                                                     bookmarkDataIsStale:nil,
                                                     error:error)
   return bkFileURL
    if error[0]
        puts error[0].description
        raise
    end
end

# Create a bookmark file NSData Object
bkData = bkURLtoData(NSURL.fileURLWithPath(opePanel.filename))
# Get NSURL path of the bookmark file NSData Object
bkURL = bkDataToURL(bkData)

上のbkURLtoDataで引数にURLを与えるとブックマークデータ(NSDataオブジェクト)が生成される。またまたブックマークデータのNSURLはbkDataToURLで取得できる。上述したようにブックマークデータはplistに保存することができて、後々読み込んでファイル操作することができる。たとえば、以下の様にする。

plist.rb
user_plist = NSUserDefaults.standardUserDefaults
# Save: @user_plist.setObject value, forKey:key
user_plist.setObject bkData, forKey:"bkData"
# Load: @user_plist.dataForKey(key)
user_plist.dataForKey("bkData")

またplistに保存されているかどうかは、ターミナルでdefaults read com.appID.AppNameと打てば確認できる。

ブックマークされたデータに対して処理をする場合は

access.rb
bkURL.startAccessingSecurityScopedResource
# Do any processes you want (File.open, for example)
bkURL.stopAccessingSecurityScopedResource

というように処理の開始と終了を宣言する必要がある。

基本的な処理は問題なくできるのだけど、複雑な処理、たとえばmacgemのsqlite3でデータベースをdb = SQLite3::Database.open bkURL.pathで開いて更にdb.execute "CREATE VIRTUAL TABLE"したりするとエラーになる(どうしたらよいかわかりません)。

なお、テンポラリディレクトリはsandboxの有無に関係なくアクセス自由なので、どうしてもうまくいかないときはNSTemporaryDirectory()のなかで作業して、最後にmoveItemAtURLでファイルを移動してもいいのかも。

temporary.rb
error = Pointer.new('@')
fileManager = NSFileManager.defaultManager
fileManager.moveItemAtURL(NSURL.fileURLWithPath(tmp_file),
    toURL:NSURL.fileURLWithPath(distination_file),
    error: error)
if error[0]
    puts error[0].description
    raise
end

もちろん、ここでdistination_fileはNSOpenPanelやNSSavePanelで指定されたURLまたはBookmarkDataのURLである必要がある。

参考

Link text

Link text

PS. App Storeで問題になる被仕向送金手数料ですが、最近ソニー銀行で無料化されたようですね。

7
8
0

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
7
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?