There’s a pretty good chance that you’re going to use Realm with something like RxSwift, ReactiveCocoa or some design pattern in which you throw objects from different threads. In most cases, objects that get tossed around from threads and operations should really “live by themselves”. Having pointers to them can create quite a lot of havoc.

Realm’s Objects can be in 2 different states. Managed or Unmanaged. You can call them “attached” or “unattached”.

1
2
3
4
5
6
7
8
9
let car = Car()
// at this point car is just an object constructed in memory.
try! realm.write{
realm.add(car)
}
//at this point car is attached to a Realm context
label.text = car.name

With the example above, you can see how easy it is to get an unattached object to an attached or managed instance. After you add the car instance to the realm, the realm instance and the car instance now know of each other.

Properly Detaching Managed Realm Objects

Since all Realm’s objects are subclasses of RealmSwift.Object, you can detach it very easily like so:

1
2
let attachedCarInstance: Car = realm.object(ofType: Car.self, forPrimaryKey: "myCarId")!
let detachedCopy: Car = Car(value: attachedCarInstance)

All you need to do is call the value convenience initializer

What if I have a generic T:Object? I want to detach that!

You’ll probably run into the fact that you can’t call convenience init on Generic symbols. This is a Swift limitation. So something like this won’t work,

1
2
//danger compiler will yell at you
let detachedCopy = T(value: genericInstance)

So what do I have to do?

First make sure you import both Realm and RealmSwift

1
2
3
4
5
6
import Realm
import RealmSwift
// later when you have a generic instance
let detachedCopy: T = T(value: genericInstance, schema: RLMSchema.partialShared())

RLMSchema is a symbol that is only available under the Realm import. If you’ve installed RealmSwift, this already should be available.

This smells a bit more since we had to access some Objective-C symbols. However offers the underlying way of how the convenience init(value: x) of Object really works by calling a required init method with a schema.