【问题标题】:SwiftUI Image does not display image from existing fileSwiftUI Image 不显示现有文件中的图像
【发布时间】:2024-01-31 02:50:01
【问题描述】:

在我的 SwiftUI 应用程序中,我有一个视图供人们编辑书籍的元数据,例如书名和作者。在这个视图中,我有一个显示图书封面图片的图片视图。

struct ImageView: View {

    @Binding var book: Book

    var body: some View {
        // coverFile is the URL to the image file.
        let image = NSImage(byReferencing: 
            book.metadata.coverFile)
        Image(nsImage: image)
            .aspectRatio(contentMode: .fit)
    }
}

当我打开一本书并设置了封面图片并打开元数据编辑器时,图片视图不显示任何内容。元数据编辑器有一个按钮来选择封面图像。当我单击按钮并从文件导入器中选择图像文件时,图像会出现在图像视图中。如果我关闭这本书,重新打开它,然后打开元数据编辑器,图像就会出现在图像视图中。但如果我重新启动应用程序、打开书本并打开元数据编辑器,图像视图将什么也没有显示。

我尝试了各种 NSImage 初始化程序。我尝试从Data 对象和NSBitmapImageRep 构建图像。

extension Book {
    func coverImage() -> NSImage {
        do {
            let data = try Data(contentsOf: metadata.coverFile)
            return NSImage(data: data) ?? NSImage()
        } catch {
            Swift.print("Error reading the image data. Error: \(error)")
        }
        
        return NSImage()
    }
}

struct ImageView: View {
    @Binding var book: Book

    var body: some View {
        let image = book.coverImage()
        Image(nsImage: image)
            .aspectRatio(contentMode: .fit)
    }
}

但是当我在图像视图中设置断点并检查image 变量时,它要么为零,要么无效。当我检查 coverFile 变量时,它会显示正确的 URL,包括 .png 扩展名。

在这个应用程序的 AppKit 版本中,我有相同的代码来创建 NSImage,并且图像显示在图像视图中。

根据 Apple 的文档,NSImage byReferencing 函数不会尝试从指定的 URL 检索数据或从该数据创建任何图像表示,直到应用程序尝试绘制图像或请求有关它的信息。如何让 SwiftUI 视图触发检索图像数据,使其显示在图像视图中?

更新

我在ImageView 结构中为图像创建了一个计算属性。

var image: NSImage {
    do {
        let data = try Data(contentsOf: book.metadata.coverFile)
        return NSImage(data: data) ?? NSImage()
    } catch {
        Swift.print("Error creating the image. Error: \(error)")
    }
        return NSImage()
}

当我运行这段代码时,try Data 调用抛出异常,catch 块运行,并且在 Xcode 的控制台中打印以下错误消息:

创建图像时出错。错误:错误域=NSCocoaErrorDomain Code=257 "无法打开文件“ImageFile”,因为您 无权查看。”

从文件导入器中选择文件可以正确创建数据。我对图像文件所在的文件夹具有读/写权限。

【问题讨论】:

    标签: macos swiftui nsimage


    【解决方案1】:

    据我了解,问题归结为懒惰地初始化 NSImage。

    您是否尝试过使用 init(contentsOfFile:) 或 init(contentsOf:)?它不会延迟初始化,因此不会导致此问题。

    【讨论】:

    • 主题是针对 macOS 的,NSImage 是 AppKit 的一部分,UIImage 仅适用于 iOS。
    • 这是一个多平台项目,所以我需要 Mac 版本的 NSImage。我正在为 iOS 版本使用 UIImage。
    • @SwiftDevJournal 您是否尝试过使用 init(contentsOfFile:) 或 init(contentsOf:)?它不会延迟初始化,因此不会导致此问题。
    • 是的,我有。无论我使用什么初始化,图像都是 nil 或无效。
    • @SwiftDevJournal 这很奇怪。您确定网址有效吗?就像您如何创建所述 URL 一样?您可以发布“单击按钮并从文件导入器中选择图像文件”时执行的代码吗?
    【解决方案2】:

    由于文件权限问题,图像无法显示。如果我打开应用沙盒并授予应用对图片文件夹的读取权限,则在我打开元数据编辑器时会显示封面图像。

    【讨论】:

      最近更新 更多