Realm-cocoa: Cannot update Optional object property with nil value

Created on 1 Mar 2017  路  10Comments  路  Source: realm/realm-cocoa

Goals

Use createOrUpdateInDefaultRealm to update Optional object property with nil value

Expected Results

Property becomes nil

Actual Results

Property doesn't become nil - it remains the same

Code Sample

class SomeClass: RLMObject {
    dynamic var intProp = 0
    dynamic var stringProp: String?

    override class func primaryKey() -> String {
        return "intProp"
    }
}


_ = try? RLMRealm.default().transaction() { _ in
    RLMRealm.default().deleteAllObjects()
}

_ = try? RLMRealm.default().transaction() { _ in
    let newObject = SomeClass()
    newObject.intProp = 1
    newObject.stringProp = "2"
    SomeClass.createOrUpdateInDefaultRealm(withValue: newObject)
}

let object = SomeClass(forPrimaryKey: 1)
assert(object != nil)
assert(object?.stringProp == "2")

_ = try? RLMRealm.default().transaction() { _ in
    let updatedObject = SomeClass()
    updatedObject.intProp = 1
    updatedObject.stringProp = nil
    SomeClass.createOrUpdateInDefaultRealm(withValue: updatedObject)
}

let updatedObject = SomeClass(forPrimaryKey: 1)
assert(updatedObject?.stringProp == nil) // breaks here

Sample project: https://github.com/kosyak/RealmOptionalTest

Version of Realm and Tooling

ProductName:    Mac OS X
ProductVersion: 10.12.4
BuildVersion:   16E163f

/Applications/Xcode.app/Contents/Developer
Xcode 8.2.1
Build version 8C1002

~/.rvm/gems/ruby-2.3.0/bin/pod
1.2.0
Realm (2.4.3)

/bin/bash
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)

/usr/local/bin/git
git version 2.11.1

#

I suspect https://github.com/realm/realm-cocoa/blob/master/Realm/RLMObjectStore.mm#L423 should be something like

id propValue = getValue(prop);
if (propValue || prop.optional) {

but not sure if I understand the whole logic.

Thanks for this awesome library!

P-2-Expected T-Bug

All 10 comments

Hi @kosyak. Thanks for reaching out to Realm. I'll have someone review what you've shared and follow-up with you soon. In the meantime though, I recommend you look at:

If you鈥檙e looking to use Realm purely from Swift, consider using Realm Swift instead. The Realm Objective鈥慍 and Realm Swift APIs are not interoperable and using them together is not supported.

You're using the Objective-C binding in Swift instead of the Swift binding in Swift. Use import RealmSwift instead of import Realm and update your code. If this doesn't help, no worries, one of the Cocoa engineers will follow-up soon. Cheers!

Hi @istx25, thanks for the reply. Indeed, I haven't clarify the environment where we use Realm: it's an Objective-C project currently migrating to Swift. Migration won't be complete in near future so we're still using Realm pod in Swift and Objective-C files.

I have updated sample project by including dummy ObjC class to reflect our use case (not sure though if that's the same as creating ObjC project and putting some Swift files in it).

Also I tried using RealmSwift in previous pure Swift sample (swift branch in the example repo) - no crashes there, cool.

Awesome, thanks for clarifying that. You are correct to use the Objective-C binding in that situation; just wanted to make sure. Someone will be in touch soon.

Thanks for getting in touch with us, and for the repro case. I've just ran it, and I'll be looking into exactly what's wrong.

(If you want to submit a PR, you're free to do so as well.)

This problem is a little more complicated than I anticipated. Basically, at the point in RLMObjectStore.mm where the setting is taking place, we don't seem to have enough information to distinguish between setting a property to nil (your test case) and not touching a property at all (our testCreateOrUpdateNestedObjects test case). I'll have to think about this some more.

See #5000 for why this issue is being closed as resolved.

I'm sorry: is this issue considered fixed? Sample project I posted in the issue still fails with the latest (2.10.0) Realm version.

Since this is a breaking change the fix won't be in a release until we release our next major version (Realm 3.0) in the near future.

Is there some good temporary solution? Both optional and RealmOptional don't work properly right now.

The most straightforward thing to do right now is probably to instantiate your model objects (by either initializing new ones or getting them out of the Realm), and then setting their properties manually within a write transaction. We regret the inconvenience.

Was this page helpful?
0 / 5 - 0 ratings