I'm building a Photo managing app that uses tags to help filter images. I decided to use SwiftData since it makes syncing images via CloudKit super easy. However, I'm having trouble fetching photos based off the tags they have. My models look something like this:
@Model
final class Photo {
var id: String? = ""
@Attribute(.externalStorage) var imageData: Data?
@Attribute(.externalStorage) var thumbnailData: Data?
var width: CGFloat?
var height: CGFloat?
var scale: CGFloat?
@Relationship(inverse: \Tag.photos)
var tags: [Tag]?
init(parent: Folder?, title: String?) {
id = UUID().uuidString
}
}
@Model
final class Tag {
var id: UUID?
var title: String?
var lastUsed: Date?
var photos: [Photo]?
init(title: String) {
id = UUID()
self.title = title
lastUsed = Date()
}
}
When I try writing the predicate to fetch an image based off tags, I run into multiple issues that either cause compile time errors or run time crashes. Here's some of things I've tried:
// Compile time error: Cannot convert value of type ... to closure result type 'any StandardPredicateExpression<Bool>'
return #Predicate<Photo> { photo in
photo?.contains(tags) == true
}
// Crashes with error: error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x6000013e4540> , to-many key not allowed here with userInfo
#Predicate<Photo> { photo in
photo?.contains {
$0.title == "some tag"
} == true
}
// Crashes with error: error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x6000013e4540> , to-many key not allowed here with userInfo of (null)
#Predicate<Photo> { photo in
photo.tags.flatMap {
$0.contains {
$0.title == "some tag"
}
} == true
}
It seems I'm running into a couple of issues issues here:
- Predicate doesn't seem to like optional values. The relationships are required to be optionals since I'm using CloudKit. I've tried force unwrapping as well and it only leads to the same errors
- Predicate doesn't seem to like Many-to-Many relationships. I'm not sure how else to go about this though since I also want an easy way to fetch the unique tags and the count of photos for each tag.
I'm wondering at this point if this is a hard limitation of SwiftData or if I'm just missing something that would allow this to work.