1

I am using SwiftUI and Realm.

I want to save an Image to the database. The image is a photo taken from the device's camera and is not stored in the gallery.

It's my understanding that I need to convert the image to NSData, but I can only find syntax that works with UIImage.

I tried

let uiImage: UIImage = image.asUIImage()

but get this error:

Value of type 'Image?' has no member 'asUIImage'

What am I doing wrong here, how can I have an Image to Realm local database?

EDIT: Thanks for the suggested "possible duplicate", but no: the duplicate (which I have already seen prior to making my post) is for UIImage (UIKit). I am using Image (SwiftUI).

Joseph
  • 691
  • 4
  • 18
  • Does this answer your question? [How can I store an Image to Realm database?](https://stackoverflow.com/questions/39866893/how-can-i-store-an-image-to-realm-database) – Isaaс Weisberg Dec 12 '22 at 08:31
  • 1
    @IsaaсWeisberg, no it doesn't. That's talking about UIImage, which is for UIKit. I am using Image, for SwiftUI. I can only find syntax to save a UIImage to Realm (through NSData), but I don't know how to convert to UIImage from Image, or save Image in some way to Realm. – Joseph Dec 12 '22 at 08:33
  • 1
    Oh, I'm sorry - well-- https://stackoverflow.com/a/57447904/9353387 This answer here is telling that `Image` is merely a type that displays images, but does not represent the image itself - and they suggest, you retain the source data that you used to create `Image` - do you think, you can get the hand on this data you used to create Image? – Isaaс Weisberg Dec 12 '22 at 08:38
  • 1
    @IsaaсWeisberg, thank you! I managed to get the UIImage data from the original data, and successfully saved to the Realm database (though had to cast from NSData to Data, for some reason) – Joseph Dec 12 '22 at 09:30
  • Heey I'm glad you did it-- although, just as a side note, I wanted to mention that storing data blobs in Realm database can be extremely slow and more commonly used and fast approach is to write files to disk and to store only the names of those files in the database. – Isaaс Weisberg Dec 12 '22 at 09:40
  • 1
    To add on the @IsaaсWeisberg great answer... Unless it's a thumbnail, don't store images in Realm. They can easily go beyond the 16Mb field capacity and the app will crash, and it will be slow per the answer. Also take a loot as [this answer](https://stackoverflow.com/questions/67268185/images-storage-performance-react-native-base64-vs-uri-path/67271381#67271381) for a bit more in depth and some options. – Jay Dec 12 '22 at 20:01

1 Answers1

2

The struct Image is only a building block for the UI in Swift UI and it is not an object that represents the literal image, but rather something that displays some image.

The common approach, is to see how you create Image - where do you get the actual image from - and to use the source, the image itself to save it.

Just as side note, I wanted to mention that storing data blobs in Realm database can be extremely slow and more commonly used and fast approach is to write files to disk and to store only the names of those files in the database.

Elaborating on this approach, you can:

  • create a folder to store your images in Library path in user domain mask

You can read about iOS Sandbox file system and where you can store stuff at Apple File System Programming Guide.

For our purposes, it will suffice to this method.

let imagesFolderUrl = try! FileManager.default.url(for: . applicationSupportDirectory, in: .userDomainMask)
    .appendingPathComponent("images_database")
  • You should check if this directory exists and create it if it doesn't - there's plenty of information about this online.
  • Then, when you have an image Data, you give it a name, you create a URL that will point to where it will be stored and then you write it.
let imageData: Data
let imageName = "some new name for this particular image - maybe image id or something"

let imageUrl = imagesFolderUrl.appendingPathComponent(imageName)
imageData.write(to: url) // Very slow operation that you should perform in background and not on UI thread
  • Then, you store the name of the image in the Realm database
  • Then, when you pull a record from Realm database and see the name of the image, you can construct the url again and read a Data from it
let record: RealmRecord
let imageName = record.imageName
let url = imagesFolder.appendingPathComponent(imageName)
let data = Data(url: imageName)

That's overly simplifying it.

Isaaс Weisberg
  • 2,296
  • 2
  • 12
  • 28
  • 1
    @Isaac, thank you for your help. When you say write files to disk, could you please elaborate a little — should I save to UserDefaults and then save the reference, or is there a better way? – Joseph Dec 20 '22 at 08:22
  • 1
    @Joseph I have edited my answer to answer your query – Isaaс Weisberg Dec 20 '22 at 09:36
  • 1
    Excellent, thank you @Isaac! For anyone else with the same question, I also found the syntax here helpful: https://stackoverflow.com/a/54546913/16370901 – Joseph Dec 22 '22 at 07:47