Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upserting an object with an embedded object crashes the app #7163

Closed
sochalewski opened this issue Mar 4, 2021 · 5 comments
Closed

Upserting an object with an embedded object crashes the app #7163

sochalewski opened this issue Mar 4, 2021 · 5 comments

Comments

@sochalewski
Copy link

sochalewski commented Mar 4, 2021

Goals

Upsert an object that contains an embedded object.

Expected Results

Upsert works flawlessly.

Actual Results

Upsert crashes an app.

2021-03-04 19:48:14.412232+0100 Example[37771:2640657] *** Terminating app due to uncaught exception 'RLMException', reason: 'Cannot set a link to an existing managed embedded object'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff20421af6 __exceptionPreprocess + 242
	1   libobjc.A.dylib                     0x00007fff20177e78 objc_exception_throw + 48
	2   Realm                               0x0000000103fcddc0 _ZN18RLMAccessorContext12createObjectEP11objc_objectN5realm12CreatePolicyEbNS2_6ObjKeyE + 3568
	3   Realm                               0x000000010410859e RLMAddObjectToRealm + 302
	4   RealmSwift                          0x0000000105ad1770 $s10RealmSwift0A0V3add_6updateySo0aB6ObjectC_AC12UpdatePolicyOtF + 1392
…
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Steps for others to Reproduce

  1. Create an instance of Realm database.
  2. Create an instance of object that contains an embedded object (MyObject).
  3. Set the embedded object to non-nil.
  4. Write the instance to the database.
  5. Create a copy of the first instance.
  6. Upsert the second instance into the database.

Code Sample

Models:

final class MyEmbeddedObject: EmbeddedObject {
    @objc dynamic var value = false
}

final class MyObject: Object {
    @objc dynamic var id = ObjectId.generate()
    @objc dynamic var embeddedObject: MyEmbeddedObject?
    
    override static func primaryKey() -> String? {
        return "id"
    }
}

Code:

let realm = try! Realm()

let myObject1 = MyObject()
myObject1.embeddedObject = MyEmbeddedObject()

try! realm.write {
    realm.add(myObject1)
}

let myObject2 = MyObject(value: myObject1)

try! realm.write {
    realm.add(myObject2, update: .modified) // ⚠️ Responsible line
}

Code that works, but I guess is a workaround instead of a solution.

try! realm.write {
    myObject2.embeddedObject = MyEmbeddedObject(value: myObject2.embeddedObject as Any)
    realm.add(myObject2, update: .modified)
}

I understand it relates how Object.init(value:) initializer works (shallow instead of deep copy), but as I call Realm.add(_:update:) with .modified instead of .all, I expected this to work properly.

Version of Realm and Tooling

Realm framework version: 10.7.0

Realm Object Server version: N/A

Xcode version: 12.4

iOS/OSX version: 14.4

Dependency manager + version: CocoaPods 1.10.1

@pavel-ship-it
Copy link
Contributor

Hi @sochalewski ,
Yes, this is a question of shallow/deep copy and therefore the workaround above is a solution.
UpdatePolicy.modified won't work in this case as in fact you're creating a copy of a link to embedded object instead of embedded object.

@sochalewski
Copy link
Author

sochalewski commented Mar 7, 2021

@pavel-ship-it Thank you for your answer, it makes sense. Then I'll close the issue.

@tgoyne tgoyne reopened this Mar 8, 2021
@tgoyne
Copy link
Member

tgoyne commented Mar 8, 2021

The code sample you posted is something that's supposed to work and we just have some overly-eager validation.

@pavel-ship-it
Copy link
Contributor

Fixed in pull request #7301

@sipersso
Copy link

@pavel-ship-it since this was fixed... in #7301 should we close the issue?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants