6

アプリケーション ディレクトリの外部にあるユーザーが選択したフォルダーに関する情報を表示する TodayWidget アプリ拡張機能を作成しています。

私のメイン アプリケーションでは、NSOpenPanel 経由で powerbox を使用してフォルダーを選択できます。その後、セキュリティ スコープのブックマークを、TodayWidget からアクセスできるアプリ グループ コンテナーのユーザー デフォルトに保存できます。

TodayWidget はブックマーク データを読み取ることができますが、URLByResolvingBookmarkDataを呼び出すと、次のエラーが発生します。

The file couldn’t be opened because it isn’t in the correct format.

メイン アプリケーションと TodayWidget の両方に、以下の権限があります。

  • com.apple.security.files.bookmarks.app-scope
  • com.apple.security.files.user-selected.read-only

Apple のドキュメントによると、セキュリティ スコープのブックマークを作成したアプリケーションのみがそれを使用できます。これらは、組み込みアプリケーションが許可されていないことを意味していると思いますか?

私は XPC の使用を検討しましたが、XPC はセキュリティ スコープのブックマークも使用できず、通常のブックマークしか使用できないため、実際には問題の解決にはなりません。コンピュータが再起動されるとすぐに、XPC プロセスはディレクトリへのアクセスを失います。

本当に必要なのは、XPC プロセスがユーザー指定のディレクトリへの読み取りアクセスを取得する方法だけです。コンピューターを再起動するたびにメイン アプリケーションを再起動する必要がない方法はありますか?

4

2 に答える 2

5

あなたはおそらくすでにこれを解決しているか、先に進んでいます。しかし、同様のことを試みているすべての人のために、これをここに残しておきます。別のアプリでセキュリティ スコープのブックマークにアクセスするには、それらを NSData として転送し、別のアプリケーションで再解決する必要があります。

私の場合、メイン アプリケーションで開いているダイアログを表示し、範囲指定されたブックマークを共有NSUserDefaultsスイートに保存します。他のアプリケーションもそのスイートの一部であり、 のコンテナにアクセスして、それらを使用可能なNSDataに解決します。NSURL

関連するコードは次のとおりです。

//Inside my main application's open function 
... get url from NSOpenPanel
BookmarkUtils.saveURLForOtherApplications(openPanel.URL!)


//Inside BookmarkUtils.swift
static func saveURLForOtherApplications(url:NSURL)->Bool{
    let defaults  = NSUserDefaults(suiteName: <#Suite-Name#>)!
    //I store them as a dictionary of path->encoded URL
    let sandboxedBookmarks:NSMutableDictionary
    if let prevBookmarks =  defaults.objectForKey(kSandboxKey) as? NSDictionary{
       sandboxedBookmarks = NSMutableDictionary(dictionary:prevBookmarks)
    }
    else{
        sandboxedBookmarks = NSMutableDictionary()
    }
    if let shareData = BookmarkUtils.transportDataForSecureFileURL(url){
        sandboxedBookmarks.setObject(shareData, forKey:url.path!)
        defaults.setObject(sandboxedBookmarks, forKey:kSandboxKey)
        defaults.synchronize()
        return true
    }
    else{
        println("Failed to save URL Data");
        return false
    }
}

static func transportDataForSecureFileURL(fileURL:NSURL)->NSData?{
    // use normal bookmark for encoding security-scoped URLs for transport between applications
    var error:NSError? = nil
    if let data =  fileURL.bookmarkDataWithOptions(NSURLBookmarkCreationOptions.allZeros, includingResourceValuesForKeys:nil, relativeToURL:nil, error:&error){
        return data;
    }
    else{
        println("Error creating transport data!\(error)")
        return nil
    }
}

それで、私の拡張機能(私の場合は今日のビュー)で、私はこのようなことをします...

class TodayViewController: ...
    ...
    override func viewDidLoad() {
        super.viewDidLoad()

        var status = [MyCoolObjects]()
        for url in BookmarkUtils.sharedURLSFromApp(){
            BookmarkUtils.startAccessingSecureFileURL(url)
            status.append(statusOfURL(url))
            BookmarkUtils.stopAccessingSecureFileURL(url)
        }

    self.listViewController.contents = status
}

関連するブックマークは次のようになります。

static func sharedURLSFromApp()->[NSURL]{
    var urls = [NSURL]()
    if let defaults  = NSUserDefaults(suiteName: <#Suite-Name#>){
        if let prevBookmarks =  defaults.objectForKey(kSandboxKey) as? NSDictionary{
            for key in prevBookmarks.allKeys{
                if let transportData = prevBookmarks[key as! NSString] as? NSData{
                    if let url = secureFileURLFromTransportData(transportData){
                        urls.append(url)
                    }
                }
            }
        }
    }
    return urls
}



static func secureFileURLFromTransportData(data:NSData)->NSURL?{
    // use normal bookmark for decoding security-scoped URLs received from another application
    var bookmarkIsStale:ObjCBool = false;
    var error:NSError? = nil;
    if let fileURL = NSURL(byResolvingBookmarkData: data, options: NSURLBookmarkResolutionOptions.WithoutUI, relativeToURL: nil, bookmarkDataIsStale: &bookmarkIsStale, error: &error){
        return fileURL
    }
    else if(bookmarkIsStale){
        println("Bookmark was stale....")
    }
    else if let resolveError = error{
        println("Error resolving from transport data:\(resolveError)")
    }
    return nil
}

このソリューションは私にとってはうまくいきます。共有 URL を解決したら、そのアプリケーションのブックマークを作成し、必要に応じて後で保存することができます。もっと良い方法があるかもしれません。Apple がこれに取り組むことを願っています。

于 2015-05-01T15:49:54.210 に答える