本文介绍了快速访问沙盒Mac应用程序中的文件访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为OS X 10.9开发带有快速沙盒的应用程序.

I am working on an app for OS X 10.9 with swift, sandboxed.

该应用需要访问SQLite数据库文件.我让用户使用NSOpenPanel选择/打开文件.然后,我使用NSUserDefaults保存文件路径,以备后用.

The app needs access to a SQLite database file. I let the user choose/open a file with NSOpenPanel. I then save the file path with NSUserDefaults for later use.

我希望每次重新启动应用程序时自动打开此文件.我从NSUserDefault获取存储的路径,但是当我使用该路径打开文件时,出现错误,提示我无权访问该文件.

I want this file to be opened automatically every time when the app is started again. I get the stored path from the NSUserDefault, but when I open the file with this path I get an error, saying I have no permission to access the file.

(无需沙箱即可工作)

书签似乎是解决我问题的方法.

It looks like bookmark's are the solution to my problem.

是否有一个很好的教程,如何在OSX应用程序中快速使用书签?还有其他建议吗?

Is there a good tutorial how to use bookmark's with swift for an osx app?Any other suggestion?

推荐答案

这是我的答案,我刚刚在 http://swiftrien.blogspot.com/2015/07/persisting-file-access-rights-between.html

Here is my answer that I've just got working in Swift 3 with a little help from http://swiftrien.blogspot.com/2015/07/persisting-file-access-rights-between.html

import Foundation
import Cocoa

var bookmarks = [URL: Data]()

func bookmarkPath() -> String
{
    var url = app.applicationDocumentsDirectory
    url = url.appendingPathComponent("Bookmarks.dict")
    return url.path
}

func loadBookmarks()
{
    let path = bookmarkPath()
    bookmarks = NSKeyedUnarchiver.unarchiveObject(withFile: path) as! [URL: Data]
    for bookmark in bookmarks
    {
        restoreBookmark(bookmark)
    }
}

func saveBookmarks()
{
    let path = bookmarkPath()
    NSKeyedArchiver.archiveRootObject(bookmarks, toFile: path)
}

func storeBookmark(url: URL)
{
    do
    {
        let data = try url.bookmarkData(options: NSURL.BookmarkCreationOptions.withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
        bookmarks[url] = data
    }
    catch
    {
        Swift.print ("Error storing bookmarks")
    }

}

func restoreBookmark(_ bookmark: (key: URL, value: Data))
{
    let restoredUrl: URL?
    var isStale = false

    Swift.print ("Restoring \(bookmark.key)")
    do
    {
        restoredUrl = try URL.init(resolvingBookmarkData: bookmark.value, options: NSURL.BookmarkResolutionOptions.withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale)
    }
    catch
    {
        Swift.print ("Error restoring bookmarks")
        restoredUrl = nil
    }

    if let url = restoredUrl
    {
        if isStale
        {
            Swift.print ("URL is stale")
        }
        else
        {
            if !url.startAccessingSecurityScopedResource()
            {
                Swift.print ("Couldn't access: \(url.path)")
            }
        }
    }

}

func allowFolder() -> URL?
{
    let openPanel = NSOpenPanel()
    openPanel.allowsMultipleSelection = false
    openPanel.canChooseDirectories = true
    openPanel.canCreateDirectories = true
    openPanel.canChooseFiles = false
    openPanel.begin
        { (result) -> Void in
            if result == NSFileHandlingPanelOKButton
            {
                let url = openPanel.url
                storeBookmark(url: url!)
            }
    }
    return openPanel.url
}

Swift 4(更新):

import Foundation
import Cocoa

var bookmarks = [URL: Data]()

func fileExists(_ url: URL) -> Bool
{
    var isDir = ObjCBool(false)
    let exists = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDir)

    return exists
}

func bookmarkURL() -> URL
{
    let urls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
    let appSupportURL = urls[urls.count - 1]
    let url = appSupportURL.appendingPathComponent("Bookmarks.dict")
    return url
}

func loadBookmarks()
{

    let url = bookmarkURL()
    if fileExists(url)
    {
        do
        {
            let fileData = try Data(contentsOf: url)
            if let fileBookmarks = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(fileData) as! [URL: Data]?
            {
                bookmarks = fileBookmarks
                for bookmark in bookmarks
                {
                    restoreBookmark(bookmark)
                }
            }
        }
        catch
        {
            print ("Couldn't load bookmarks")
        }

    }
}

func saveBookmarks()
{
    let url = bookmarkURL()
    do
    {
        let data = try NSKeyedArchiver.archivedData(withRootObject: bookmarks, requiringSecureCoding: false)
        try data.write(to: url)
    }
    catch
    {
        print("Couldn't save bookmarks")
    }
}

func storeBookmark(url: URL)
{
    do
    {
        let data = try url.bookmarkData(options: NSURL.BookmarkCreationOptions.withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
        bookmarks[url] = data
    }
    catch
    {
        Swift.print ("Error storing bookmarks")
    }

}

func restoreBookmark(_ bookmark: (key: URL, value: Data))
{
    let restoredUrl: URL?
    var isStale = false

    Swift.print ("Restoring \(bookmark.key)")
    do
    {
        restoredUrl = try URL.init(resolvingBookmarkData: bookmark.value, options: NSURL.BookmarkResolutionOptions.withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale)
    }
    catch
    {
        Swift.print ("Error restoring bookmarks")
        restoredUrl = nil
    }

    if let url = restoredUrl
    {
        if isStale
        {
            Swift.print ("URL is stale")
        }
        else
        {
            if !url.startAccessingSecurityScopedResource()
            {
                Swift.print ("Couldn't access: \(url.path)")
            }
        }
    }

}

func allowFolder() -> URL?
{
    let openPanel = NSOpenPanel()
    openPanel.allowsMultipleSelection = false
    openPanel.canChooseDirectories = true
    openPanel.canCreateDirectories = true
    openPanel.canChooseFiles = false
    openPanel.begin
        { (result) -> Void in
            if result == NSFileHandlingPanelOKButton
            {
                let url = openPanel.url
                storeBookmark(url: url!)
            }
    }
    return openPanel.url
}

要使用此代码,必须首先调用NSOpenPanel,以便用户可以选择要授予您访问权限的文件夹. NSOpenPanel必须作为书签存储并保存到磁盘.

To use this code you must first call NSOpenPanel so the user can select which folders to give you access to. The NSOpenPanel must be stored as a bookmark and saved to disk.

let url = allowFolder()
saveBookmarks()

重新启动应用程序时,您必须调用

When you restart the application you must call

loadBookmarks()

然后,您的应用程序将具有与用户选择文件夹时相同的访问级别.希望这对某人有帮助.

then your app will have the same level of access as it did when the user selected the folder. Hope this helps someone.

这篇关于快速访问沙盒Mac应用程序中的文件访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 23:06