I'd like to initialize an object using Object(value:) passing in an instance of Object, and as a result expect an unmanaged object with all of its properties (and their nested objects) unmanaged as well.
Obtain an unmanaged copy of the Object instance, with all of its child objects and relations being unmanaged (recursively).
It crashes when saving the newly created object. Why?
The new object is unmanaged, and its array (RLMArray) of other objects are also unmanaged, but the instances of that array are actually managed.
(I did this in Objective-C):
Create a new Object class, subclassing RLMObject, and another OtherObject class, also subclassing RLMObject. Object must contain a RLMArray of OtherObjects, complying with the OtherObject protocol (RLM_ARRAY_TYPE(OtherObject);).
Populate the database with sample data, including adding objects to the RLMArray<OtherObject><OtherObject *> otherObjects array.
(I did this in Swift):
let newObject = Object(value: object) // object is a managed object
print(newObject.realm) // nil
print(newObject.otherObjects) // nil
print(newObject.otherObjects.firstObject()!) // non-nill, it actually prints its Realm. Expected: nil
let newObject = Object(value: object) // object is a managed object
print(newObject.realm) // nil
print(newObject.otherObjects.realm) // nil
print(newObject.otherObjects.firstObject()!.realm) // non-nill, it actually prints its Realm. Expected: nil
ProductName: Mac OS X
ProductVersion: 10.13.5
BuildVersion: 17F77
/Applications/Xcode.app/Contents/Developer
Xcode 9.4
Build version 9F1027a
/usr/local/bin/pod
1.5.3
Realm (3.1.0)
Realm (~> 3.1.0)
/** But I actually tested on Realm (3.7.2) (~> 3.7.0) and this bug is still present there! **/
/bin/bash
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
carthage not found
(not in use here)
/usr/bin/git
git version 2.15.1 (Apple Git-101)
Also just come across this issue, anything that I can assist with or is this in hand? @rogerluan have you worked around this for the time been?
@christoff-1992 Luckily, in my use case, I actually didn't need the RLMArray of objects cloned, so I just cleared them (i.e. removeAllObjects()) and it worked fine.
If you do need them, though, you'd have to remove all objects from Object, clone them manually (i.e. using YourNestedObject(value:) for each object of the array), and then re-populate the array of the newly cloned object.
Lemme know if that works 馃憤
Thanks, @rogerluan unfortunately for myself removing all the objects won't be an option. I am creating an unmanaged copy of the object as there is no undo functionality in Realm. The workaround will work but I have the joys of many nested objects 馃ぃ. @tgoyne / @bmunkholm is this the expected behaviour when copying an object using Object(value:) or is this a bug? Thanks.
Object(value:) performing a shallow copy is an unfortunate design decision and not a bug.
The main problem with changing it is that it's a breaking change: it's unlikely that anyone specifically wants to be accessing managed objects from their standalone copy of the parent, but if they aren't actually using those properties then changing to a deep copy would make what's currently a fairly cheap operation into something potentially very slow and memory hungry. It's not that rare to have a schema where every object is reachable from every other object, which means that Object(value:) would suddenly start copying the entire Realm into memory whenever it's used.
That said, we do clearly need a way to perform a deep copy out of a Realm. Early on we were wary about building something because it looked like it'd be a footgun that lead people in the wrong direction, but that hasn't really been a concern for years.
Gotcha, that makes sense @tgoyne . Could that be solved by passing an optional parameter to the copy function? Sounds like that would solve the issue and it'd be up to the user if they explicitly want to perform a shallow copy or not.
A potentially very simple solution would be a max depth parameter, which would also sorta let us punt on dealing with object cycles. Might have odd implications when the value isn't a Realm object, though? If you pass in a dictionary we have to fully recur and convert nested values to Realm objects.
Closing due to age, if you have any more questions please open a new issue.
Thanks.
Most helpful comment
A potentially very simple solution would be a max depth parameter, which would also sorta let us punt on dealing with object cycles. Might have odd implications when the value isn't a Realm object, though? If you pass in a dictionary we have to fully recur and convert nested values to Realm objects.