【问题标题】:How to read image from file system within macOS app如何从 macOS 应用程序中的文件系统读取图像
【发布时间】:2021-01-05 08:51:09
【问题描述】:

应用程序可能会打开一个对话框,允许选择图像并将其显示给用户。用户选择图片的代码是:

let myFiledialog = NSOpenPanel()
myFiledialog.prompt = "Upload image"
myFiledialog.canChooseDirectories = false
myFiledialog.canChooseFiles = true
myFiledialog.allowedFileTypes = ["png", "jpg", "jpeg"]
myFiledialog.allowsMultipleSelection = false
myFiledialog.begin {  [weak self] result -> Void in
      guard 
           result.rawValue == NSApplication.ModalResponse.OK.rawValue,
           let selectedPath = myFiledialog.url?.path
      else {
            return
      }
      guard let image = NSImage(contentsOfFile: selectedPath) else {
          return
      }
      someImageView.image = image
      UserDefaults.standard.set(selectedPath, forKey: "imagePath")
}

我正确显示图像。这个想法是用户可以关闭应用程序,打开它并查看图像。

我正在获取图像名称:

let pathName = UserDefaults.standard.string(forKey: "imagePath")

我比较了设置断点pathName == selectedPath,它们是相等的。

但是,做

NSImage(contentsOfFile: pathName!)

nil

这是否与我需要获取读取文件系统中的数据的权限有关?我应该将用户图像保存在可以访问它们的其他地方吗?也许也可以将 NSUserDefaults 设置为 images.data

感谢您的帮助。

【问题讨论】:

  • 你被沙盒化了。您需要书签文件的 URL。参见例如developer.apple.com/documentation/foundation/nsurl/…
  • 不要问UserDefaults能为你做什么。询问您可以为安全范围的书签做什么。
  • 感谢@matt,我可以看到书签方法返回了一个 URL。我应该使用 NSUserDefaults 来保存那个 URL 吗?

标签: swift macos


【解决方案1】:

感谢@matt 在 cmets 中的链接,我实现了答案。留在这里以防对任何人有帮助。

  1. 为应用程序添加权利。点击 App -> Target -> Signin & Capabilities -> App Sandbox 并更改文件访问类型的“权限和访问”。 Xcode 会询问您是否要创建授权文件。接受。如果您不需要它,请还原您所做的更改。现在您将拥有文件<AppName>/<AppName>Release.entitlements。添加允许用户使用应用范围书签和 URL (Apple Docs) 的权利。这是文件的样子:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.files.user-selected.read-only</key>
    <true/>
    <key>com.apple.security.files.bookmarks.app-scope</key>
    <true/>
</dict>
</plist>
  1. 创建一个名为 Codable 的结构,用于保存书签数据和图像名称(或您可能拥有并需要保存的任何 Codable 数据)。
struct CodableImage: Codable {
    let bookmarkData: Data
    let name: String
}
  1. 为网址添加书签:
do {
    let data = try url.bookmarkData()
    let codableImage = CodableImage(bookmarkData: data, name: "Awesome image")
    UserDefaults.standard.set(try? JSONEncoder().encode(codableImage), forKey: "kImageKey")
} catch {
    print(error)
}
  1. 检索数据

首先从UserDefaults获取CodableImage

guard 
    let encodedImageData = UserDefaults.standard.value(forKey: "kImageKey") as? Data,
    let codableImage = try? JSONDecoder().decode(CodableImage.self, from: encodedImageData)
else {
    // Data could not be read or decoded or both :(
    return
}

解析书签数据,如果解析的数据过期,则更新书签:

var isBookmarkStale = false
guard let url = try? URL(resolvingBookmarkData: codableImage.bookmarkData, bookmarkDataIsStale: &isBookmarkStale) else {
    return nil
}

if isBookmarkStale {
    print("Bookmark is stale. renewing.")
    // If bookmark data is stale, all occurences have to be updated.
            
    let _ = try? url.bookmarkData()
}

最后,从解析的 url 创建图像:

let image = NSImage(contentsOf: url)

感谢URL Bookmarks: yes and no 提供陈旧的数据更新逻辑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-23
    • 2016-06-01
    • 2021-05-26
    • 2020-09-12
    • 1970-01-01
    • 2012-04-12
    相关资源
    最近更新 更多