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

[bug] Potential crash in UITableView when collection changes observed synchronously #113

Open
abeintopalo opened this issue Sep 25, 2018 · 2 comments
Assignees
Milestone

Comments

@abeintopalo
Copy link

Let's take the sample code from the readme:

let realm = try! Realm()
let laps = realm.objects(Lap.self)

Observable.changeset(from: laps)
  .subscribe(onNext: { results, changes in
    if let changes = changes {
      // it's an update
      print(results)
      print("deleted: \(changes.deleted)")
      print("inserted: \(changes.inserted)")
      print("updated: \(changes.updated)")
    } else {
      // it's the initial data
      print(results)
    }
  })

The above code sets synchronousStart to true by default.

Here is the implementation of Observable.changeset(from: synchronousStart):

public static func changeset(from collection: E, synchronousStart: Bool = true)
        -> Observable<(AnyRealmCollection<E.ElementType>, RealmChangeset?)> {

        return Observable.create { observer in
            if synchronousStart {
                observer.onNext((collection.toAnyCollection(), nil))
            }

            let token = collection.toAnyCollection().observe { changeset in

                switch changeset {
                    case .initial(let value):
                        guard !synchronousStart else { return }
                        observer.onNext((value, nil))
                    case .update(let value, let deletes, let inserts, let updates):
                        observer.onNext((value, RealmChangeset(deleted: deletes, inserted: inserts, updated: updates)))
                    case .error(let error):
                        observer.onError(error)
                        return
                }
            }

            return Disposables.create {
                token.invalidate()
            }
        }
    }

If the database is modified continuously from a background thread it can happen that the database changes in between invoking code observer.onNext((collection.toAnyCollection(), nil)) and guard !synchronousStart else { return }. As a result one change is swallowed and the next change that is delivered by observer.onNext((value, RealmChangeset(deleted: deletes, inserted: inserts, updated: updates))) will be incompatible with the previously saved state of the collection in the view model.
Because of the lost/swallowed change of the collection the incremental update of UITableView will crash the app if the change to be applied is not valid. (Invalid update, etc)
The current workaround for me is to set _ synchronousStart_ to false.

So, basically synchronous start with the current implementation does not work in some situation.

@M0rtyMerr
Copy link
Member

Similar with - #74
Can reproduce it

@M0rtyMerr M0rtyMerr self-assigned this Jun 5, 2020
@M0rtyMerr M0rtyMerr added the bug label Jun 5, 2020
@tristangrichard
Copy link

Anything new on this? Any workaround?

@JoeMatt JoeMatt added the crash label Jan 22, 2022
@JoeMatt JoeMatt changed the title Potential crash in UITableView when collection changes observed synchronously [bug] Potential crash in UITableView when collection changes observed synchronously Jan 22, 2022
@JoeMatt JoeMatt self-assigned this Jan 22, 2022
@JoeMatt JoeMatt added this to the 5.0.5 milestone Jan 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants