macOS sandbox 文件夹授权

macOS如果想上苹果市场发布的话,那么必须要遵守苹果沙盒协议,这样应用存储默认都是沙盒路径隔离用户文件系统,那么这个时候需要访问 /User/xxx/Library/Developer/ 这种文件夹的时候直接访问是会被拒绝的,那既然这样就肯定要授权了,等同意了在访问就名正言顺了。

那么要如何进行这种操作呢,首先想到的肯定是先把这个文件打开再说,然后当次的权限就有了,然后就是解决后续依然有权限访问问题这个时候就用到bookmark这个东东就是转门干这个用的,下面一步一步的来实现这个功能

例子授权 /user/xxx/Library/Developer/ 路径为例

首先获取文件绝对路径

func getAbsolutePath(path: String) -> String? {
    let pw = getpwuid(getuid())
    guard let home = pw?.pointee.pw_dir else {
        return nil
    }
    let homePath = FileManager.default.string(withFileSystemRepresentation: home, length: Int(strlen(home)))
    return "(homePath)/(path)"
}

let path = getAbsolutePath("/Library/Developer")
// /User/xxx/Library/Developer/

打开文件夹获取权限

func openFinder() {
    let fm = FileManager.default
    let filepath = getAbsolutePath(path: "Library/Developer/")!
    print("filepath is (filepath)")
    let url = URL(filePath: filepath)
    
    let dialog = NSOpenPanel()
    dialog.message = "文件夹授权以提供服务"
    dialog.prompt = "选择"
    dialog.allowsOtherFileTypes = false
    dialog.canChooseFiles = false
    dialog.canChooseDirectories = true
    dialog.directoryURL = url
    
    dialog.begin { response in
        if response == .OK, let folderPath = dialog.url {
            // 可以判断一下是不是想要的文件夹,这个时候已经有权限了。
            // 保存书签权限
        }
    }
}

保存书签权限

书签数据存在bookmark中,以后用的时候取出来用。

private func saveBookmarkData(for workDir: URL) {
    do {
        let bookmarkData = try workDir.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)

        print("save book mark data")
        // save in UserDefaults
        UserDefaults.standard.setValue(bookmarkData, forKey: "bookmark")
    } catch {
        print("Failed to save bookmark data for (workDir)", error)
    }
}

判断路径是否授权

private func restoreFileAccess() -> Bool {
    do {
        if let bookmark = UserDefaults.standard.object(forKey: "bookmark") as? Data {
            var isStale = false
            let url = try URL(resolvingBookmarkData: bookmark, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale)
            guard url.startAccessingSecurityScopedResource() else {
                return false
            }
            return true
        }
        return false
    } catch {
        print("Error resolving bookmark:", error)
        return false
    }
}

完整代码

以下为完整代码

import SwiftUI

struct ContentView: View {
    @State var fileSize: Int = 0
    @State var canAccess: Bool = false
    
    func getAbsolutePath(path: String) -> String? {
        let pw = getpwuid(getuid())
        guard let home = pw?.pointee.pw_dir else {
            return nil
        }
        let homePath = FileManager.default.string(withFileSystemRepresentation: home, length: Int(strlen(home)))
        return "(homePath)/(path)"
    }
    
    private func saveBookmarkData(for workDir: URL) {
        do {
            let bookmarkData = try workDir.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)

            print("save book mark data")
            // save in UserDefaults
            UserDefaults.standard.setValue(bookmarkData, forKey: "bookmark")
        } catch {
            print("Failed to save bookmark data for (workDir)", error)
        }
    }
    
    private func restoreFileAccess() -> Bool {
        do {
            if let bookmark = UserDefaults.standard.object(forKey: "bookmark") as? Data {
                var isStale = false
                let url = try URL(resolvingBookmarkData: bookmark, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale)
                guard url.startAccessingSecurityScopedResource() else {
                    return false
                }
                return true
            }
            return false
        } catch {
            print("Error resolving bookmark:", error)
            return false
        }
    }
    
    func openFinder() {
        let fm = FileManager.default
        let filepath = getAbsolutePath(path: "Library/Developer/")!
        print("filepath is (filepath)")
        let url = URL(filePath: filepath)
        
        let dialog = NSOpenPanel()
        dialog.message = "Choose your directory"
        dialog.prompt = "Choose"
        dialog.allowsOtherFileTypes = false
        dialog.canChooseFiles = false
        dialog.canChooseDirectories = true
        dialog.directoryURL = url
        
        dialog.begin { response in
            if response == .OK, let folderPath = dialog.url {
                saveBookmarkData(for: folderPath)
            }
        }
    }
    
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("占用容量: (fileSize)")
            
            Button {
                if !canAccess {
                    openFinder()
                }
            } label: {
                if canAccess {
                    Text("已授权")
                } else {
                    Text("授权")
                }
            }
        }
        .padding()
        .onAppear {
            if restoreFileAccess() {
                canAccess = true
            } else {
                canAccess = false
            }
            print("access is (canAccess)")
        }
    }
}

#Preview {
    ContentView()
}

原文地址:https://blog.csdn.net/xo19882011/article/details/134787254

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_42548.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注