Clifton Labrum
Clifton Labrum

Reputation: 14068

Make Realm Loop Generic and Reusable in Swift

Swift 4, Xcode 9.2

Here are a few Realm classes I have:

class Dog: Object {
  @objc dynamic var id = UUID().uuidString
  @objc dynamic var updated = Date()
  //Other properties...
}

class Cat: Object {
  @objc dynamic var id = UUID().uuidString
  @objc dynamic var updated = Date()
  //Other properties...
}

class Horse: Object {
  @objc dynamic var id = UUID().uuidString
  @objc dynamic var updated = Date()
  //Other properties...
}

Let's say I have some code like this where I compare two realms and create an object with a specific Dog class:

let remoteDogs = remoteRealm.objects(Dog.self)

for remoteDog in remoteDogs{
  if let localDog = realm.objects(Dog.self).filter("id = %@",remoteDog.id).first{
    // Update
    if localDog.updated < remoteDog.updated{
      //Remote is newer; replace local with it
      realm.create(Dog.self, value: remoteDog, update:true)
    }
  }
}

This works great, but I need to do this same stuff on a whole bunch of Realm classes that I have. So I'm trying to make it more generic like this:

let animals = [Dog.self, Cat.self, Horse.self]

for animal in animals{
  let remoteAnimals = remoteRealm.objects(animal)

  for remoteAnimal in remoteAnimals{
    if let localAnimal = realm.objects(animal).filter("id = %@",remoteAnimal.id).first{
      // Update
      if localAnimal.updated < remoteAnimal.updated{
        //Remote is newer; replace local with it
        realm.create(animal, value: remoteAnimal, update:true)
      }
    }
  }
}

This sort of works, but anytime I want to reference the property of an object (like with remoteAnimal.id and remoteAnimal.updated) then the compiler complains because it doesn't know what kind of object a remoteAnimal is.

Has anyone done something like this before? Any ideas how I can do this so that I don't have to write this same code over and over for each of my Realm classes? Thanks!

Upvotes: 0

Views: 131

Answers (1)

Josh Homann
Josh Homann

Reputation: 16327

Realm Object does not have id or updated. You can have your Dog, Cat and Horse classes inherit from an Animal class that is a subclass of Object and that does have id or updated. Since these properties are defined on Animal they will be usable in all of the subclasses (Dog, Cat, Horse).

class Animal: Object {
  @objc dynamic var id = UUID().uuidString
  @objc dynamic var updated = Date()
  //Other properties...
}

class Dog: Animal {
  //Other properties...
}

EDIT you can also abuse Objective C's NSObject setValue:forKey: to set the property by name. This is very sloppy typing and not good object oriented design but it does work. Here is a playground:

import UIKit

class A: NSObject {
  @objc var customProperty = 0
}
let a = A()
a.setValue(5, forKey: "customProperty")
print(a.customProperty)

Upvotes: 2

Related Questions