首页 > 解决方案 > SwiftUI Image 不显示现有文件中的图像

问题描述

在我的 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 代码 = 257 “无法打开文件“ImageFile”,因为您无权查看它。”

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

标签: macosswiftuinsimage

解决方案


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

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


推荐阅读