Search code examples
swiftrealmkey-value-coding

Iterate over properties of an object (in Realm, or maybe not)


I'm working on a project that uses Realm for the database (that will come into the picture later). I've just discovered key-value coding and I want to use it in converting a TSV table into object properties (using the column headers from the table as the keys). Right now it looks like this:

    let mirror = Mirror(reflecting: newSong)
    for property in mirror.children {
        if let index = headers.index(of: property.label!) {
            newSong.setValue(headers[index], forKey: property.label!)
        } else {
            propertiesWithoutHeaders.append(property.label!)
        }
    }

Is there a way to iterate over properties without a mirror? I really could have sworn that I read in the Realm documentation (or maybe even in Apple's KVC documentation) that you can do something like for property in Song.properties or for property in Song.self.properties to achieve the same thing.

Besides it being a little more efficient, the main reason I want to do this is because in the same place I think I read this, I think they said that the iterating (or the KVC?) only works with Strings, Ints, Bools and Dates, so it would automatically skip the properties that are Objects (since you can't set them with in the same way). The above code is actually a simplification of my code, in the actual version I'm currently skipping over the Objects like this:

let propertiesToSkip = ["title", "artist", "genre"]
for property in mirror.children where !propertiesToSkip.contains(property.label!) {
...

Did I imagine this .properties thing? Or, is there a way to iterate in this way, automatically skipping over Objects/Classes without having to name them as I do above?

Thanks :)


Solution

  • No you didn't imagine it. :)

    Realm exposes the schema encompassing the properties of each type of model in a database in two places: in the parent Realm instance, or in an Object itself.

    In the Realm instance:

    // Get an instance of the Realm object
    let realm = try! Realm()
    
    // Get the object schema for just the Mirror class. This contains the property names
    let mirrorSchema = realm.schema["Mirror"]
    
    // Iterate through each property and print its name
    for property in mirrorSchema.properties {
       print(property.name)
    }
    

    Realm Object instances expose the schema for that object via the Object.objectSchema property.

    Check out the schema property of Realm in the Realm Swift Documentation for more information on what kind of data you can get out of the schema properties. :)