Read and write permission for user selected folder in Mac OS app?

前端 未结 3 1203
清歌不尽
清歌不尽 2020-12-30 12:12

I am developing MAC OS app which have functionality to create file on the behalf of your. First user select folder for storing file (One time at start of app) and then user

相关标签:
3条回答
  • 2020-12-30 12:51

    Here is my Answer How to do implement and persist Read and write permission of user selected folder in Mac OS app?

    GitHub Example Project link

    First :

    Add user-selected and bookmarks.app permissions in entitlement file :

    <key>com.apple.security.files.user-selected.read-write</key>
    <true/>
    <key>com.apple.security.files.bookmarks.app-scope</key>
    <true/>
    

    Then i created class for all bookmark related function required for storeing, loading ... etc bookmarks app.

    import Foundation
    import Cocoa
    
    var bookmarks = [URL: Data]()
    
    func openFolderSelection() -> URL?
    {
        let openPanel = NSOpenPanel()
        openPanel.allowsMultipleSelection = false
        openPanel.canChooseDirectories = true
        openPanel.canCreateDirectories = true
        openPanel.canChooseFiles = false
        openPanel.begin
            { (result) -> Void in
                if result.rawValue == NSApplication.ModalResponse.OK.rawValue
                {
                    let url = openPanel.url
                    storeFolderInBookmark(url: url!)
                }
        }
        return openPanel.url
    }
    
    func saveBookmarksData()
    {
        let path = getBookmarkPath()
        NSKeyedArchiver.archiveRootObject(bookmarks, toFile: path)
    }
    
    func storeFolderInBookmark(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 getBookmarkPath() -> String
    {
        var url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
        url = url.appendingPathComponent("Bookmarks.dict")
        return url.path
    }
    
    func loadBookmarks()
    {
        let path = getBookmarkPath()
        bookmarks = NSKeyedUnarchiver.unarchiveObject(withFile: path) as! [URL: Data]
        for bookmark in bookmarks
        {
            restoreBookmark(bookmark)
        }
    }
    
    
    
    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)")
                }
            }
        }
    
    }
    

    Then open folder selection using 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. Then your app will have the same level of access as it did when the user selected the folder.

    To open NSOpenPanel :

    let selectedURL = openFolderSelection()
    saveBookmarksData()
    

    and to load existing bookmark after app close :

    loadBookmarks()
    

    Thats it. I Hope it will help someone.

    0 讨论(0)
  • 2020-12-30 12:53

    I found the best and working answer here - reusing security scoped bookmark

    Super simple, easy to understand and does the job pretty well.

    The solution was :-

    var userDefault = NSUserDefaults.standardUserDefaults()
    var folderPath: NSURL? {
        didSet {
            do {
                let bookmark = try folderPath?.bookmarkDataWithOptions(.SecurityScopeAllowOnlyReadAccess, includingResourceValuesForKeys: nil, relativeToURL: nil)
                userDefault.setObject(bookmark, forKey: "bookmark")
            } catch let error as NSError {
                print("Set Bookmark Fails: \(error.description)")
            }
        }
    }
    
    func applicationDidFinishLaunching(aNotification: NSNotification) {
        if let bookmarkData = userDefault.objectForKey("bookmark") as? NSData {
            do {
                let url = try NSURL.init(byResolvingBookmarkData: bookmarkData, options: .WithoutUI, relativeToURL: nil, bookmarkDataIsStale: nil)
                url.startAccessingSecurityScopedResource()
            } catch let error as NSError {
                print("Bookmark Access Fails: \(error.description)")
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-30 13:08

    Add user-selected and bookmarks.app permissions in entitlement file :

    <key>com.apple.security.files.user-selected.read-write</key>
    <true/>
    <key>com.apple.security.files.bookmarks.app-scope</key>
    <true/>
    

    Then open folder selection using 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. Then your app will have the same level of access as it did when the user selected the folder.

    0 讨论(0)
提交回复
热议问题