我正在开发MAC OS应用程序,它具有代表您创建文件的功能。第一个用户选择用于存储文件的文件夹(在应用程序启动时一次),然后用户可以使用苹果脚本选择要在所选文件夹上创建的文件的类型和名称(在应用程序启动时选择的文件夹)。当我在权利文件中添加temporary-exception
以下时,我可以创建文件,但是它无法应用苹果审核小组,但可以在沙盒中使用。
准则2.4.5(i) - 表现 我们已确定为此应用程序请求的一个或多个临时权利例外不合适且不会被授予:
com.apple.security.temporary-exception.files.home-relative-path.read-write
/FolderName/
我找到了:
Enabling App Sandbox - 允许应用编写可执行文件。
并且
Enabling User-Selected File Access - Xcode在目标编辑器的“摘要”选项卡中提供了一个弹出菜单,其中包含对用户明确选择的文件和文件夹进行只读或读/写访问的选项。当您启用用户选择的文件访问权限时,您可以以编程方式访问用户使用NSOpenPanel
对象打开的文件和文件夹,以及用户使用NSSavePanel
对象保存的文件。
使用以下代码创建文件:
let str = "Super long string here"
let filename = getDocumentsDirectory().appendingPathComponent("/xyz/output.txt")
do {
try str.write(to: filename, atomically: true, encoding: String.Encoding.utf8)
} catch {
// failed to write file – bad permissions, bad filename, missing permissions, or more likely it can't be converted to the encoding
}
还尝试在NSOpenPanel对象的权利文件中添加com.apple.security.files.user-selected.read-write
:
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
有没有办法让Apple审核小组批准对用户所选文件夹具有读写权限的Mac App?
答案 0 :(得分:5)
这是我的答案 如何在Mac OS应用程序中实现和持久保存用户所选文件夹的读写权限?
第一:
在权利文件中添加user-selected
和bookmarks.app
权限:
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.files.bookmarks.app-scope</key>
<true/>
然后我为存储,加载...等书签应用程序所需的所有书签相关功能创建了类。
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)")
}
}
}
}
然后使用NSOpenPanel
打开文件夹选择,以便用户可以选择允许您访问的文件夹。 NSOpenPanel
必须存储为书签并保存到磁盘。然后,您的应用将具有与用户选择文件夹时相同的访问级别。
打开NSOpenPanel
:
let selectedURL = openFolderSelection()
saveBookmarksData()
并在应用关闭后加载现有书签:
loadBookmarks()
多数民众赞成。 我希望它会帮助别人。
答案 1 :(得分:3)
在权利文件中添加user-selected
和bookmarks.app
权限:
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.files.bookmarks.app-scope</key>
<true/>
然后使用NSOpenPanel
打开文件夹选择,以便用户可以选择允许您访问的文件夹。 NSOpenPanel
必须存储为书签并保存到磁盘。然后,您的应用将具有与用户选择文件夹时相同的访问级别。
答案 2 :(得分:0)
更新到 Swift 5(感谢 Jay!)
structure(list(surname_sender = c("Ajite", "Dikmen", "Dikmen",
"Dikmen", "Dikmen", "Jylmaz", "Jylmaz", "Jylmaz", "Kandejas",
"Kandejas", "Kandejas", "Kandejas", "Kizildag", "Kizildag", "Kizildag",
"Kizildag", "Kizildag", "Motta", "Motta", "Motta", "Motta", "Motta",
"Motta", "Nordfel'dt", "Nordfel'dt", "Poloma", "Sio", "Ture",
"Ture", "Ture", "Ture", "Ture", "Uhansson", "Uhansson", "Uhansson",
"Uhansson"), surname_receiver = c("Poloma", "Kizildag", "Poloma",
"Ture", "Uhansson", "Kandejas", "Poloma", "Uhansson", "Motta",
"Nordfel'dt", "Ture", "Uhansson", "Dikmen", "Motta", "Nordfel'dt",
"Ture", "Uhansson", "Dikmen", "Jylmaz", "Kizildag", "Poloma",
"Ture", "Uhansson", "Ture", "Uhansson", "Ture", "Dikmen", "Jylmaz",
"Kandejas", "Kizildag", "Motta", "Poloma", "Kandejas", "Kizildag",
"Sio", "Uhansson"), passes = c(4L, 4L, 4L, 4L, 6L, 4L, 5L, 4L,
4L, 5L, 4L, 9L, 10L, 6L, 4L, 5L, 8L, 5L, 4L, 6L, 4L, 4L, 5L,
4L, 6L, 13L, 5L, 5L, 4L, 9L, 8L, 7L, 14L, 8L, 5L, 4L), mean_passer_x = c(64.7,
44.41875, 44.41875, 44.41875, 44.41875, 68.725, 68.725, 68.725,
75.2919444444445, 75.2919444444445, 75.2919444444445, 75.2919444444445,
29.5423333333333, 29.5423333333333, 29.5423333333333, 29.5423333333333,
29.5423333333333, 44.31, 44.31, 44.31, 44.31, 44.31, 44.31, 8.60416666666667,
8.60416666666667, 58.6384615384615, 52.46, 38.2090952380952,
38.2090952380952, 38.2090952380952, 38.2090952380952, 38.2090952380952,
51.7642857142857, 51.7642857142857, 51.7642857142857, 51.7642857142857
), mean_passer_y = c(46.9, 38.7083333333333, 38.7083333333333,
38.7083333333333, 38.7083333333333, 35.3533333333333, 35.3533333333333,
35.3533333333333, 10.7833333333333, 10.7833333333333, 10.7833333333333,
10.7833333333333, 23.6785, 23.6785, 23.6785, 23.6785, 23.6785,
34.6552777777778, 34.6552777777778, 34.6552777777778, 34.6552777777778,
34.6552777777778, 34.6552777777778, 32.2166666666667, 32.2166666666667,
65.3, 25.7, 46.9388571428571, 46.9388571428571, 46.9388571428571,
46.9388571428571, 46.9388571428571, 7.25, 7.25, 7.25, 7.25)), row.names = c(NA,
-36L), class = c("tbl_df", "tbl", "data.frame"))
答案 3 :(得分:-1)
我在这里找到了最佳且可行的答案-reusing security scoped bookmark
超级简单,易于理解,并且做得很好。
解决方案是:-
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)")
}
}
}