Sandbox - 访问带有副文件的主文件 Access sidecar files in a Mac sandboxed app

1. 访问带有副文件的主文件

比如访问视频 .mp4 文件时,同时应该有权限访问对应的字幕文件

参考:Access sidecar files in a Mac sandboxed app
Question:
I need to access sidecar XMP files in a document-based photo editor application. The image files are the documents, and I need to access the sidecar XMP file when the user open and save an image document.
Is it possible to access sidecar files (such as XMP) in a sandboxed document-based application?
I understand that it’s not possible by default, but what is the minimal temporary security exception that is needed to allow that?
Is there a workaround for this without using temporary exception?
Note that it’s impossible to guarantee the the image files document-scoped bookmarks to the side-cars (as they might created by other apps on different platforms), so this solution won’t work.

Answer:
While this question is old I thought I would share my solution. You can add an entry to your CFBundleDocumentTypes section
in your apps info.plist with the NSIsRelatedItemType set to true. Then your sandboxed app will be able to open any file the
user gives permission to with the same name but has the extensions that you list.
Here is an example for an xmp sidecar file:

<key>CFBundleDocumentTypes</key>
<array>
    <dict>
        <key>CFBundleTypeExtensions</key>
        <array>
            <string>xmp</string>
        </array>
        <key>CFBundleTypeName</key>
        <string>XMP sidecar</string>
        <key>CFBundleTypeRole</key>
        <string>None</string>
        <key>NSIsRelatedItemType</key>
        <true/>
    </dict>
</array>

测试代码:

// 通过NSOpenPanel打开源文件: /Users/victor/Desktop/SanboxTestFolder_2/1.txt
// 可以访问到源文件的data
let contents = FileManager.default.contents(atPath: textField.stringValue)

logTextView.string += String.init(describing: contents) + "\n\n"

失败: 但是即使我在Info.plist 中添加了上面的内容,还是不能访问到 /Users/victor/Desktop/SanboxTestFolder_2/1.xmp文件的内容

继续搜索答案:“Related item” file not written due to Sandbox
翻译:自定义class 实现协议 NSFilePresenter

  • presentedItemURL: sidecar 文件路径,和主文件路径只是extension不一样
  • primaryPresentedItemURL: 主文件路径
  1. right after creating an istance of an object implementing the protocol NSFilePresenter I have to register it calling the class method “addFilePresenter” of NSFileCoordinator like this “NSFileCoordinator.addFilePresenter(filePresenter)”
  2. in the info.plist in the doc type flagged as NSIsRelatedItemType=true the key “CFBundleTypeRole” must be "Editor" (and not “None” as it was in my case)

代码:

import Foundation
class ZWFilePresenter: NSObject {
    private var queue: OperationQueue
    private var sourceURL: URL
    @available(*, unavailable)
    override init() {
        fatalError()
    }
    
    init(sourceURL: URL) {
        self.sourceURL = sourceURL
        self.queue = .init()
        super.init()
        NSFileCoordinator.addFilePresenter(self)
    }
    
    deinit {
        NSFileCoordinator.removeFilePresenter(self)
    }
    
    func saveSidecarFileTest(content: String) {
        guard let sidecarURL = self.presentedItemURL else {
            return
        }
        let coordinator = NSFileCoordinator.init(filePresenter: self)
        var error: NSError?
        coordinator.coordinate(writingItemAt: sidecarURL, error: &error) { url in
            print("--- url:\(url)")
            
            do {
                try content.write(to: sidecarURL, atomically: true, encoding: .unicode)
            } catch let writeErr {
                print(writeErr)
            }
        }
        
    }

    func loadSidecarFile() -> String? {
        guard let sidecarURL = self.presentedItemURL else {
            return nil
        }
        let coordinator = NSFileCoordinator.init(filePresenter: self)
        var error: NSError?
        var result: String?
        coordinator.coordinate(readingItemAt: sidecarURL, error: &error) { url in
            print("--- url:\(url)")
            do {
                try result = String.init(contentsOf: url, encoding: .unicode)
            } catch let doErr {
                print(doErr)
            }
        }
        return result
    }
    
    
}

extension ZWFilePresenter: NSFilePresenter {
    var presentedItemURL: URL? {
        let ret = sourceURL.deletingPathExtension().appendingPathExtension("xmp")
        return ret
       
    }
    var primaryPresentedItemURL: URL? {
        return sourceURL
    }
    var presentedItemOperationQueue: OperationQueue {
        return self.queue
    }
    
    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值