0

I have a CoreData Entity called Data that has an attribute called asset for image data:

extension Data {
    static func createImage(label: Label, image: UIImage, context: NSManagedObjectContext) {
        let newData = Data(context: context)
        newData.id = UUID()
        newData.type = "image"
        newData.label = label
        newData.setValue(image.pngData(), forKey:
                        "asset")
        newData.date = Date()
        context.saveContext()
    }

I can't seem to figure out how to load the binary image data into an UIImage.

var fetchRequest: FetchRequest<Data>
var data: FetchedResults<Data> {
        fetchRequest.wrappedValue
}

init(label: Label){
        let sortDescriptor = NSSortDescriptor(keyPath: \Data.date, ascending: false)
        let predicate = NSPredicate(format: "label == %@", label)
        self.label = label
        fetchRequest = FetchRequest<Data>(entity: Data.entity(), sortDescriptors: [sortDescriptor], predicate: predicate)
}

  var body: some View {
        LazyVGrid(columns: columns, alignment: .leading){
            ForEach(data, id: \.self) { dataItem in
                GeometryReader { gr in
                    Image(uiImage: UIImage(data: dataItem.asset ?? Data()) ?? UIImage())
}
}

And I get the error 'NSObject' is not convertible to 'Data'

I've also tried let uiImage: UIImage = UIImage(data: dataItem.asset)!

Which gives the error Cannot convert value of type 'Data?' to expected argument type 'Data'

This is how I set up the asset attribute: enter image description here

1
  • could you try: if let imgData = dataItem.asset, let img = UIImage(data: imgData) { Image(uiImage: img) } else { Image(uiImage:UIImage()) } Commented Aug 20, 2021 at 2:56

1 Answer 1

1

Your first error is because you've named your core data entity as Data, and were trying convert Foundation.Data to your own class

I suggest you rename your core data entity to prevent such mistakes in the future.

In case you can't do that for some reason(not this case, generally), and you have two classes with the same name from different modules, you can select the needed class with the specifying module before, like Foundation.Data

Second your error was because you were trying to unwrap the result of UIImage instead of your own data.

When you need to unwrap an item before passing it to a function. I suggest you to use one of the following methods:

  1. Unwrap variable using .map and .flatMap:
dataItem.asset
    .flatMap { asset in
        UIImage(data: asset)
    }.map { uiImage in
        Image(uiImage: uiImage)
    }
  1. Use .map and extend Data. I prefer this one for better readability. You could've extends UIImage in the same way to return Image, but for SwiftUI view it would look too strange and decrease readability to me:
dataItem.asset?
    .toUIImage()
    .map { uiImage in
        Image(uiImage: uiImage)
    }
---
extension Data {
    func toUIImage() -> UIImage? {
        UIImage(data: self)
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

awesome, thanks so much! I renamed the entity and unwrapped the item using the flatMap you suggested and it worked.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.