SwiftUI Image does not display image from existing file

In my SwiftUI app I have a view for people to edit a book's metadata, such as its title and author. In this view I have an image view that shows the book's cover image.

struct ImageView: View {

    @Binding var book: Book

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

When I open a book that I've set a cover image and open the metadata editor, the image view displays nothing. The metadata editor has a button to choose a cover image. When I click the button and choose an image file from the file importer, the image appears in the image view. If I close the book, reopen it, and open the metadata editor, the image appears in the image view. But if I restart the app, open the book, and open the metadata editor, the image view displays nothing.

I have tried the various NSImage initializers. I tried building the image from a Data object and from NSBitmapImageRep. But when I set a breakpoint in the image view and check the image variable, it's either nil or invalid. When I check the coverfile variable, it displays the proper URL, including the .png extension.

In an AppKit version of this app, I have the same code to create the NSImage, and the image displays in the image view.

How do I get an existing image file to display in the image view without clicking the Choose Cover button and choosing the file again from the file importer?

Answered by szymczyk in 691009022

The image does not display because of a file permissions problem. If I turn on the App Sandbox and give the app Read access to the Pictures folder, the cover image appears when I open the metadata editor.

If the image is not saved somewhere and reloaded at start in the Book metaData, it is logical it doesn't show. How did you do this in the other version of your App ?

I suspect your problem is with NSImage(byReferencing url:)

Apple say:

This method initializes the image object lazily

and

It does not attempt to retrieve the data from the specified URL or create any image representations from that data until an app attempts to draw the image or request information about it.

and

Because this method doesn’t actually create image representations for the image data, your app should do error checking before attempting to use the image

I suggest that after...

let image = NSImage(byReferencing: book.metadata.coverFile)

...you immediately check "image", and try to do something with it, to trigger the actual data retrieval.

(It looks like just placing it in an Image(nsImage:) is not enough to do this.)

I created an outlet for an image view and called a function in the view controller's viewDidAppear method to load the metadata. I had the following line of code to set the image:

coverImageView.image = NSImage(contentsOf: book.metadata.coverFile)

Accepted Answer

The image does not display because of a file permissions problem. If I turn on the App Sandbox and give the app Read access to the Pictures folder, the cover image appears when I open the metadata editor.

SwiftUI Image does not display image from existing file
 
 
Q