Search code examples
objective-crealmrealm-migration

Realm Objective-C migration error


I am seeing crashes via Crashlytics and hearing from customers that the application is crashing right as they open it.

This is narrowed down to the application migrating one of the realm databases. I have not been able to recreate the issue unfortunately because I am not able to make any sense of the error I am seeing.

I have logic that checks when the app starts up to check and see if the realm needs to be compacted. When doing that the realm determines that it needs to be migrated and hit the migration block.

    config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
        if (oldSchemaVersion < 17) {
            [migration enumerateObjects:Event.className block:^(RLMObject *oldObject, RLMObject *newObject) {
                NSString *className = [[oldObject[@"endDateTime"] objectSchema] className];
                if ([className isEqualToString:@"DateObject"]) {
                    newObject[@"endDateTime"] = oldObject[@"endDateTime"][@"value"];
                }
            }];
        }
    };

Due to a mistake on my end when doing previous migrations I was manually checking to see if a property if of a specific type before deciding to migrate it. Unfortunately when doing so the oldObject which should be of type RLMObject seems to be of type NSTaggedDate according to Crashlytics

    [__NSTaggedDate objectSchema]: unrecognized selector sent to instance 0xe41bf592ee000000
    Fatal Exception: NSInvalidArgumentException
    0  CoreFoundation                 0x186419d04 __exceptionPreprocess
    1  libobjc.A.dylib                0x185668528 objc_exception_throw
    2  CoreFoundation                 0x1864271c8 __methodDescriptionForSelector
    3  CoreFoundation                 0x18641f6b0 ___forwarding___
    4  CoreFoundation                 0x18630501c _CF_forwarding_prep_0
    5  MY_mobile_ios_common         0x10199c8c0 __34+[MYRealm getRealmConfigByName:]_block_invoke_2 (MYRealm.m:44)
    6  Realm                          0x1011b6598 -[RLMMigration enumerateObjects:block:] (RLMMigration.mm:99)
    7  MY_mobile_ios_common         0x10199c830 __34+[MYRealm getRealmConfigByName:]_block_invoke (MYRealm.m:40)
    8  Realm                          0x1011b6ab4 -[RLMMigration execute:] (RLMMigration.mm:131)
    9  Realm                          0x1012297ec std::__1::__function::__func<+[RLMRealm realmWithConfiguration:error:]::$_1, std::__1::allocator<+[RLMRealm realmWithConfiguration:error:]::$_1>, void (std::__1::shared_ptr<realm::Realm>, std::__1::shared_ptr<realm::Realm>, realm::Schema&)>::operator()(std::__1::shared_ptr<realm::Realm>&&, std::__1::shared_ptr<realm::Realm>&&, realm::Schema&) (RLMRealm.mm:410)
    10 Realm                          0x10124fa90 std::__1::__function::__func<realm::Realm::update_schema(realm::Schema, unsigned long long, std::__1::function<void (std::__1::shared_ptr<realm::Realm>, std::__1::shared_ptr<realm::Realm>, realm::Schema&)>, std::__1::function<void (std::__1::shared_ptr<realm::Realm>)>, bool)::$_2, std::__1::allocator<realm::Realm::update_schema(realm::Schema, unsigned long long, std::__1::function<void (std::__1::shared_ptr<realm::Realm>, std::__1::shared_ptr<realm::Realm>, realm::Schema&)>, std::__1::function<void (std::__1::shared_ptr<realm::Realm>)>, bool)::$_2>, void ()>::operator()() (memory:4625)
    11 Realm                          0x101181f64 realm::ObjectStore::apply_schema_changes(realm::Group&, unsigned long long, realm::Schema&, unsigned long long, realm::SchemaMode, std::__1::vector<realm::SchemaChange, std::__1::allocator<realm::SchemaChange> > const&, std::__1::function<void ()>) (object_store.cpp:753)
    12 Realm                          0x10124bbb8 realm::Realm::update_schema(realm::Schema, unsigned long long, std::__1::function<void (std::__1::shared_ptr<realm::Realm>, std::__1::shared_ptr<realm::Realm>, realm::Schema&)>, std::__1::function<void (std::__1::shared_ptr<realm::Realm>)>, bool) (functional:1860)
    13 Realm                          0x101226a10 +[RLMRealm realmWithConfiguration:error:] (functional:1860)
    14 MY_mobile_ios_common         0x10199cba0 +[MYRealm mainRealmCompact] (MYRealm.m:137)
    15 MY App                     0x1002b49dc -[AppDelegate compactRealmIfNeeded] (AppDelegate.m:808)
    16 MY App                     0x1002af940 -[AppDelegate application:didFinishLaunchingWithOptions:] (AppDelegate.m:48)

Any thoughts on what I could be doing wrong here, am about to just delete the realm databases and force the users to go back through the initial loading of data again.

ProductName: Mac OS X ProductVersion: 10.12.6 BuildVersion: 16G1036

/Applications/Xcode.app/Contents/Developer Xcode 9.1 Build version 9B55

/usr/local/bin/pod 1.3.1 Realm (2.10.2) Realm (= 2.10.2)

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

(not in use here)

/usr/local/bin/git git version 2.12.2


Solution

  • The crash log is telling you that your call to [oldObject[@"endDateTime"] objectSchema] is seeing oldObject[@"endDateTime"] evaluate to an NSDate, which does not respond to -objectSchema. If the endDateTime property can be of different types depending on which schema version you're updating from, you'll need to do further checks on the object before sending -objectSchema to it.