安全范围书签 - 书签解析但仍无法访问文件

时间:2018-02-02 16:20:12

标签: swift avplayer security-scoped-bookmarks

编辑:在底部添加了其他信息

我有一个基于沙盒的基于文档的应用程序,可以将用户选择的quicktime影片加载到AVPlayer中,一切都运行良好。

现在我正在升级代码,以便它使用Security Scoped书签来获取URL,而不仅仅是存储URL字符串,这样持久存储将允许在重新启动应用程序时加载影片。创建书签时,它存储在托管对象的Data变量中。

出于某种原因,这破坏了AVPlayer。虽然我已经从用户选择的URL创建了一个书签,并且可以在重新启动应用程序时解析书签中的URL,但是电影没有正确加载到AVPlayer中我无法找出原因...我已经确认从书签中解析的URL确实指向电影文件。

我还为项目添加了相应的权利。

这是我的代码:

用户选择要加载的电影和创建书签的功能

 @IBAction func loadMovie(_ sender: Any) {

    let openPanel = NSOpenPanel()
    openPanel.title = "Select Video File To Import"
    openPanel.allowedFileTypes = ["mov", "avi", "mp4"]

    openPanel.begin { (result: NSApplication.ModalResponse) -> Void in
        if result == NSApplication.ModalResponse.OK {

            self.movieURL = openPanel.url
            self.player = AVPlayer.init(url: self.movieURL!)

            self.setupMovie()

            if self.loadedMovieDatabase.count > 0 {
                print("Movie Object Exists. Adding URL String")
                self.loadedMovieDatabase[0].urlString = String(describing: self.movieURL!)
            } else {
                print("No Movie Object Exists Yet.  Creating one and adding URL String")
                let document = NSDocumentController.shared.currentDocument as! NSPersistentDocument
                let myManagedObjectContext = document.managedObjectContext!
                let newMovie = NSEntityDescription.insertNewObject(forEntityName: "Movie", into: myManagedObjectContext) as! MovieMO
                self.loadedMovieDatabase.append(newMovie)
                self.loadedMovieDatabase[0].urlString = String(describing: self.movieURL!)
            }

            // create Security-Scoped bookmark - Added 2/1/18
            do {
                try self.loadedMovieDatabase[0].bookmark = (self.movieURL?.bookmarkData(options: NSURL.BookmarkCreationOptions.withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil))!
            } catch {
                print("Can't create security bookmark!")
            }

        }
    }

}

将书签解析为网址并加载电影的功能

       // initialize AVPlayer with URL stored in coreData movie object if it exists and is a valid path
    if loadedMovieDatabase.count > 0 {
        // initialize with saved movie path if it is valid (from security bookmark data)
        // let myURL = URL(string: loadedMovieDatabase[0].urlString!) <- replaced with new code below
        print("Loading URL from Bookmark")
        var urlResult = false
        var myURL : URL
        do {
            try myURL = URL.init(resolvingBookmarkData: loadedMovieDatabase[0].bookmark, bookmarkDataIsStale: &urlResult)!
            print("URL Loaded from Bookmark")
            print("URL is", myURL)
            let isSecuredURL = myURL.startAccessingSecurityScopedResource()
            print("IsSecured = ", isSecuredURL)
            player = AVPlayer.init(url: myURL)
            print("Setting Up Movie")
            setupMovie()
        } catch {
            // No Data in bookmark so load default ColorBars movie instead
            print("No Security Bookmark Available. Reverting to Default Color Bars")
            let myURL = URL(string: initialMoviePath)
            player = AVPlayer.init(url: myURL!)
            setupMovie()
        }
    } else {
        // load default ColorBars movie instead
        print("Nothing was loaded so just set up a new document.")
        let myURL = URL(string: initialMoviePath)
        player = AVPlayer.init(url: myURL!)
        setupMovie()
    }

我是安全范围书签的新手,所以我希望这对以前与他们合作的人来说显而易见。

我想知道这是否有问题:

let isSecuredURL = myURL.startAccessingSecurityScopedResource()

也许我这称错了?有时我发现Apple的文档含糊不清且令人困惑......任何见解都会受到赞赏!

修改

我相信我知道为什么会这样,但我不确定如何解决它......

myURL.startAccessingSecurityScopedResource()

总是返回FALSE ...根据文档意味着它不起作用。此外,当电影文件位于我的桌面上时,已解决的URL如下所示(这可能是正常的,我不知道。):

文件:///Users/me/Library/Containers/myapp/Data/Desktop/sample_on_desktop.mov

苹果文档引用了一个事实,即文档范围不能使用系统中的文件(又名“/ Library”),但我的权利设置为使用应用程序范围的书签,我的书签是使用nil创建的relativeURL的标志:所以这应该不是问题。

1 个答案:

答案 0 :(得分:4)

我偶然偶然发现了答案......

对于初学者,当我解析URL时,我没有使用允许您包含OPTIONS的方法,因此我的URL在没有安全范围的情况下得到了解决。我要解决的原始代码是:

try myURL = URL.init(resolvingBookmarkData: loadedMovieDatabase[0].bookmark, bookmarkDataIsStable: &urlResult)!

当我应该在这里使用带有选项的版本时:

try myURL = URL.init(resolvingBookmarkData: loadedMovieDatabase[0].bookmark, Options: URL.bookmarkResolutionOptions.withSecurityScope, relativeTo: nil, bookmarkDataIsStable: &urlResult)!

基本上,我在预测列表中使用了第一个init选项Xcode,其中包含“resolvingBookmarkData:”,当我应该在列表中进一步查看时。 (这就是我发现错误的方法。)

另请注意,使用...

非常重要
URL.bookmarkResolutionOptions.withSecurityScope

而不是

URL.bookmarkCreationOptions.withSecurityScope

...当你解析你的网址时,或者它似乎无法正常工作。

因此结束了我对这个问题的沮丧:)我希望这个解释可以帮助其他人面对这个问题!