2

I need to save a list of images as NSData in Realm. I tried using Realm optional but realmOptional<NSdata> can't be used because realmOptional does not conform to type NSDate.
Is there a way to do it?

Edit: Basically all I want is to be able to store a list of NSData but optional something like:

@objc dynamic var photos: List<NSData>?
Dr.jacky
  • 3,341
  • 6
  • 53
  • 91
  • Does this answer your question? [How to put an image in a Realm database?](https://stackoverflow.com/questions/33299523/how-to-put-an-image-in-a-realm-database) – denis_lor Jan 21 '20 at 20:59
  • Thanks for the answer my question is to how can I store an optional array of data in realm basically – peiman ramezaninejad Jan 21 '20 at 21:19
  • 1
    Why do you need an optional List? It's just a List, which *represents* a to-many relationship, and if you don't store anything in it, it will have a count of 0 and take no space. Can you clarify the use case with some code? – Jay Jan 22 '20 at 17:44
  • 1
    @jay Lets say you are decoding and you can't be sure that the JSON returned will have an array (or List) of items. We'll need to make it optional somehow. – user139816 Aug 03 '21 at 11:03
  • 1
    @user139816 See the [updated documentation](https://docs.mongodb.com/realm/sdk/ios/data-types/supported-property-types/) for List types (note the optional column). An array and a List, while they have similar functions, they are very different options. Lists represent forward relationships whereas an array is a set of objects 'within' an object. – Jay Aug 03 '21 at 18:05
  • I resolved my similar issue (decoding potentially missing json data into Realm) by simply using decodeIfPresent in the decoder – user139816 Aug 06 '21 at 12:56
  • @user139816 My answer might be of some use for you. I had the same issue as you, and found a clean way of decoding. Still using decodeIfPresent(), but with less boilerplate. – akaffe Nov 04 '21 at 16:52

3 Answers3

4

Solution for optional List types when using Decodable

In my case I needed an optional List because I'm decoding json into Realm objects, and it's possible that the property might not exist in the json data. The typical workaround is to manually decode and use decodeIfPresent(). This isn't ideal because it requires boilerplate code in the model:

class Driver: Object, Decodable {
    var vehicles = List<Vehicle>()
    var name: String = ""
    // etc

    public required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.vehicles = try container.decodeIfPresent(List<Vehicle>.self, forKey: .vehicles) ?? List<Vehicle>()
        self.name = try container.decode(String.self, forKey: .name)
        // etc
    }
}

However, we can avoid the boilerplate by extending KeyedDecodingContainer with an overload for List types. This will force all lists to be decoded using decodeIfPresent():

  • Realm v5:

    class Driver: Object, Decodable {
        var vehicles = List<Vehicle>()
        var name: String = ""
        //etc
    }
    
    class Vehicle: Object, Decodable {
        var drivers = List<Driver>()
        var make: String = ""
        // etc
    }
    
    extension KeyedDecodingContainer {
        // This will be called when any List<> is decoded
        func decode<T: Decodable>(_ type: List<T>.Type, forKey key: Key) throws -> List<T> {
          // Use decode if present, falling back to an empty list
            try decodeIfPresent(type, forKey: key) ?? List<T>()
        }
    }
    
  • Realm v10+:

    class Driver: Object, Decodable {
        @Persisted var vehicles: List<Vehicle>
        @Persisted var name: String = ""
        // etc
    }
    
    class Vehicle: Object, Decodable {
        @Persisted var drivers: List<Driver>
        @Persisted var make: String = ""
        // etc
    }
    
    extension KeyedDecodingContainer {
        // This will be called when any @Persisted List<> is decoded
        func decode<T: Decodable>(_ type: Persisted<List<T>>.Type, forKey key: Key) throws -> Persisted<List<T>> {
            // Use decode if present, falling back to an empty list
            try decodeIfPresent(type, forKey: key) ?? Persisted<List<T>>(wrappedValue: List<T>())
        }
    }
    

Edit: Clarified code examples, fixed typo

akaffe
  • 447
  • 3
  • 11
2

The List cannot be optional, but the Objects in the list can be optional, you have to declare it like:

@Persisted var value: List<Type?>

Here is the link with the Supported data types https://www.mongodb.com/docs/realm/sdk/swift/data-types/supported-property-types/

Johana Lopez 1327
  • 165
  • 1
  • 3
  • 14
1

according to https://realm.io/docs/swift/latest/#property-cheatsheet you can not define optional lists in realm

omid
  • 15
  • 5