Storing multiple images in swift data – Swift

by
Maya Patel
swift-data swift5

Quick Fix: To store multiple images in Swift data, create a new model named ‘Photo’ that holds the image data as ‘Data’ type. Then, in ‘SwiftDataModel’, add a ‘photos’ property with the ‘[Photo]’ type, allowing a one-to-many relationship. Use ‘@Relationship(deleteRule: .cascade)’ to automatically delete photos when deleting the parent using ‘@Model’. This approach resolves the warnings caused by storing an array of ‘​Data’ in ‘SwiftDataModel’.

The Problem:

In Swift, I have a data model that stores various types of data such as amounts, dates, and text. Within this model, I want to include the functionality to store multiple images, allowing users to easily save and access collections of images associated with different entries in the data model. However, I’m unsure how to implement this feature effectively while keeping the code organized and maintainable.

The Solutions:

Solution 1: Using a New Model to Store Image Data

To store multiple images in Swift data, you can create a new model that holds the image data and establish a one-to-many relationship between this new model and your existing SwiftDataModel:

// Define the new model for storing image data
@Model class Photo {
    var id: UUID // Optionally add other fields if needed
    @Attribute(.externalStorage) var photo: Data
    
    init(photo: Data) {
        self.id = UUID()
        self.photo = photo
    }
}

In your SwiftDataModel, add a property to hold an array of Photo objects. This will create a one-to-many relationship between the two models:

// Modify the `SwiftDataModel` to include a relationship to `Photo`
@Model
class SwiftDataModel {
    @Relationship(deleteRule: .cascade) var photos: [Photo]
    // Other properties and methods...
}

With this setup, you can store multiple images by creating instances of the Photo model and adding them to the photos array in your SwiftDataModel object. When you save the SwiftDataModel instance, the associated Photo objects and their image data will also be saved.

Note: Using @Relationship(deleteRule: .cascade) allows you to automatically remove the photos when their parent SwiftDataModel object is deleted.

Solution 2:

Swift’s “`.externalStorage“` attribute merely suggests to SwiftData something should be stored outside of the underlying SQLite, but it doesn’t necessary honours that request. It is important to remember that saving photo’s Data in as external storage is completely transparent for a SwiftData user. except you can’t use them in Predicates.

One last thing to note is that you can add other attributes to an externally stored, such as Cloud Encryption:

@Attribute(.externalStorage, .allowsCloudEncryption) var avatar: Data

Solution 3: Use [Data] as Type

Use the [Data] type as the attribute type to store an array of images in Swift data. This allows you to store multiple images as a single attribute.

Here’s how you can modify your code:

@Attribute(.externalStorage) var photos: [Data]

Now, you can store an array of images in the photos attribute.

Note: Be aware of the advantages and disadvantages of storing photos (and large data) in this way. See the discussion in the provided link for more information.

Solution 4: SwiftDataModel

In addition to the syntax that allows you to store one image in Swift data, you can store an array of images by changing the type of the `photo` attribute to `[Data]?`. This will allow you to save multiple images as Data blobs and access them later via the `SwiftDataModel` parent.
“`
@Model
class SwiftDataModel {
// Session Data
var record_type: WorkRecordType
var amount: Int
var nameOfSession: String
var date: Date
var canvas: Data
var taps: Int
@Attribute(.externalStorage) var photos: [Data]?
// Doc Scan Data
}
“`
Keep in mind that you cannot use these images in Predicates because the external files are not visible to the underlying data store.

Q&A

How can I store multiple images in Swift data?

Create a new model that holds the image data and add a [Photo] property to the SwiftDataModel.

What’s the difference between storing images as Data blobs and using @Attribute(.externalStorage)?

Images stored as Data blobs can’t be used in Predicates, while images stored with @Attribute(.externalStorage) can.

Can I use [Data] as the type for photos instead of @Attribute(.externalStorage)?

Yes, you can, but you won’t be able to use those images in Predicates.

Video Explanation:

The following video, titled "How To Store An Image In SwiftData | SwiftData Tutorial | #8 ...", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

... All of this really helps my channel grow and allows me ... store data in SwiftData. We'll also look at how to read this data and display an image ...