Realm-cocoa: In-Memory Realm loses inserted data unless at least one notification block is attached

Created on 10 Feb 2017  路  5Comments  路  Source: realm/realm-cocoa

As the title says, unless I have at least one notification block added to an in-memory Realm, data disappears as soon as the function call from which it has been inserted returns.
I just need to attach an observer to any one Realm instance, then everything works.

I have a static constant containing my configuration defined like this:

class RealmStore : NSObject {
    static let configuration:Realm.Configuration = Realm.Configuration(inMemoryIdentifier: "InMemoryRealm")
...

I have a single point of entry for write operations:

private static func performWriteOperation(op: (Realm) -> Void) {
        let realm = try! Realm(configuration: self.configuration)
        do {
            try realm.write {
                op(realm)
            }
        } catch {
            fatalError("Write operation failed")
        }

        print("Total leagues ", realm.objects(League.self).count)
}

(I have made sure that it's ALWAYS being called on the main thread, although this doesn't seem to make any difference)

This is how insertion of a league looks:

    private static func insert(fromNotification notification: PriceService.Notification, replaceAllData:Bool) {
        performWriteOperation(op:insert(notification))
    }

    private static func insert(_ notification: PriceService.Notification) -> (Realm) -> Void {

        return { realm in

            switch notification {
            case .newLeagues(let notification):
                notification.leagues.forEach { self.insert($0)(realm) }
       (etc...)
    }

    private static func insert(_ notification: LeagueNotification) -> (Realm) -> Void {
        return { realm in
            let league = League.with(notification: notification)
            realm.add(league, update: true)
        }
    }

(again, this is being called on the main thread)

I receive a lot of different entities after the leagues. This is my console output *WITHOUT any notificationBlocks attached to the realm or any results:*

Handling:  .newLeagues(132)
Total leagues  132
Handling:  .newTeams1333
Total leagues  0
Handling:  .newEvents(2110)
Total leagues  0
Handling:  .updatedLines
Total leagues  0
Handling:  .updatedLines
Total leagues  0
Handling:  .updatedLines
Total leagues  0
Handling:  .updatedLines
Total leagues  0
Handling:  .updatedLines
Total leagues  0

As soon as I add a notificationBlock of some kind:

let realm = try! Realm(configuration: RealmStore.configuration)
notificationBlock = realm.addNotificationBlock { _ in }

Everything seems to work as expected:

Handling:  .newLeagues(132)
Total leagues  132
Handling:  .newTeams1333
Total leagues  132
Handling:  .newEvents(2109)
Total leagues  132
Handling:  .newEvents(2109)
Total leagues  132
Handling:  .updatedLines
Total leagues  132
Handling:  .updatedLines
Total leagues  132`

I'm just creating adding an empty notificationBlock directly on a realm instance but observing on a Results object has the same effect. ..

Also, if I change my configuration to a file-based one, the problem goes away.

Realm version: realm-swift-2.4.2

Xcode version: 8.2.1

iOS version: 10.1, Same behaviour with the Simulator

Dependency manager + version: Downloaded binaries from GitHub

T-Help

Most helpful comment

@istx25 I'm having the same problem but I'm running all my in-memory realms on non-ui threads. If I create a strongly referenced in-memory realm i cannot use it in other threads as it is not thread safe. But if I don't have a strong reference I'll lose that realm and all the data with it as mentioned above.

How to solve this issue?

All 5 comments

Hi @kasperwelner. Thanks for reaching out about this. I'll have one of the engineers review what you've shared and follow-up soon. Cheers!

The documentation on in-memory Realms contains the following notice:

Notice: When all in-memory Realm instances with a particular identifier go out of scope with no references, all data is freed for that Realm. It is recommended that you hold onto a strong reference to any created in-memory Realms for the duration of your app.

In the code snippets you've provided it looks like the Realm instances you create don't outlive the functions that open them. Notifications change things slightly as they inherently extend the lifetime of the Realm.

Making a strong reference to the Realm solved it. Thx 馃憤

Awesome, glad to hear @kasperwelner. We're here if you need anything else! :)

@istx25 I'm having the same problem but I'm running all my in-memory realms on non-ui threads. If I create a strongly referenced in-memory realm i cannot use it in other threads as it is not thread safe. But if I don't have a strong reference I'll lose that realm and all the data with it as mentioned above.

How to solve this issue?

Was this page helpful?
0 / 5 - 0 ratings