title: Realm addNotificationBlock gives me an out of bounds
body: <p>This is a difficult one that is too intermittent for me to track down. I've seen it on several rare occasions but only once in development and only in the last month, or so.</p>
  
  <p>Sometimes, when I am notified of changes, the returned objects array is empty but the modifications list has indexes within it.</p>
  
  <pre><code>let results = realmService.getThings()
  
  self.token = results.addNotificationBlock { changes in
  
    switch changes {
  
      case .initial:
        break
  
    case .update(let objects, _, _, let modifications):
  
      // Modifications has indexes, objects is empty.
  
      let updatedObjects = modifications
      self.doSomething(for: modifications.map({ objects[$0] }))
  
    case .error(let error):
      log.error(error)
  }
  </code></pre>
  
  <ol>
  <li>Is there anything fundamentally wrong with this code?</li>
  <li>Should this be a safe operation?</li>
  <li>If I guard against this scenario will I get out of
  sync with the changes that are happening?</li>
  </ol>
  
  <p>Here's some code to reproduce. Only seeing this for deletions.</p>
  
  <p>I added a UITableView and UIButtons for add and modify.</p>
  
  <p>What I don't understand is, when I delete a row the deletions print out as:</p>
  
  <pre><code>(lldb) po deletions
  ▿ 2 elements
    - 0 : 6
    - 1 : 19
  </code></pre>
  
  <p>The output of this code for me is:</p>
  
  <pre><code>Initial 20
  Delete: CEB53276-03AB-4DED-9807-D5109199FB73
  19 objects. Delete: 6,19
  2017-06-03 16:04:00.799 RealmTest[49654:2598964] *** Terminating app due to uncaught exception 'RLMException', reason: 'Index 19 is out of bounds (must be less than 19)'
  *** First throw call stack:
  (
      0   CoreFoundation                      0x0000000106426b0b __exceptionPreprocess + 171
      1   libobjc.A.dylib                     0x0000000103c50141 objc_exception_throw + 48
      2   Realm                               0x0000000102d1de96 _ZL10throwErrorP8NSString + 646
      3   Realm                               0x0000000102d1a2e7 _ZL15translateErrorsIZ28-[RLMResults objectAtIndex:]E3$_3EDaOT_P8NSString + 103
      4   Realm                               0x0000000102d1a21e -[RLMResults objectAtIndex:] + 110
      5   RealmSwift                          0x0000000103605246 _TFC10RealmSwift7Resultsg9subscriptFSix + 118
      6   RealmTest                           0x00000001029c29bf _TFFFC9RealmTest14ViewController11viewDidLoadFT_T_U_FGO10RealmSwift21RealmCollectionChangeGCS1_7ResultsCS_5Model__T_U0_FSiS4_ + 31
      7   RealmTest                           0x00000001029c2a0d _TTRXFo_dSi_oC9RealmTest5ModelzoPs5Error__XFo_iSi_iS0_zoPS1___ + 45
      8   RealmTest                           0x00000001029c61b9 _TPA__TTRXFo_dSi_oC9RealmTest5ModelzoPs5Error__XFo_iSi_iS0_zoPS1___.56 + 89
      9   libswiftCore.dylib                  0x00000001059965ba _TFEsPs10Collection3mapurfzFzWx8Iterator7Element_qd__GSaqd___ + 762
      10  RealmTest                           0x00000001029c1856 _TFFC9RealmTest14ViewController11viewDidLoadFT_T_U_FGO10RealmSwift21RealmCollectionChangeGCS1_7ResultsCS_5Model__T_ + 2038
      11  RealmSwift                          0x0000000103606fff _TFFC10RealmSwift7Results20addNotificationBlockFFGOS_21RealmCollectionChangeGS0_x__T_CSo20RLMNotificationTokenU_FTGSqGCSo10RLMResultsCSo9RLMObject__GSqCSo19RLMCollectionChange_GSqPs5Error___T_ + 367
      12  RealmSwift                          0x00000001035ce445 _TTRXFo_oGSqGCSo10RLMResultsCSo9RLMObject__oGSqCSo19RLMCollectionChange_oGSqPs5Error____XFdCb_dGSqGS_S0___dGSqS1__dGSqCSo7NSError___ + 149
      13  Realm                               0x0000000102bb3195 _ZZ23RLMAddNotificationBlockIN5realm7ResultsEEP20RLMNotificationTokenP11objc_objectRT_U13block_pointerFvS5_P19RLMCollectionChangeP7NSErrorEbENKUlRKNS0_19CollectionChangeSetESt13exception_ptrE_clESG_SH_ + 741
      14  Realm                               0x0000000102bb2bd4 _ZN5realm24CollectionChangeCallback4ImplIZ23RLMAddNotificationBlockINS_7ResultsEEP20RLMNotificationTokenP11objc_objectRT_U13block_pointerFvS7_P19RLMCollectionChangeP7NSErrorEbEUlRKNS_19CollectionChangeSetESt13exception_ptrE_E5afterESI_ + 52
      15  Realm                               0x0000000102ad513a _ZN5realm24CollectionChangeCallback5afterERKNS_19CollectionChangeSetE + 58
      16  Realm                               0x0000000102ad50a5 _ZZN5realm5_impl18CollectionNotifier13after_advanceEvENK3$_9clINSt3__111unique_lockINS4_5mutexEEENS1_8CallbackEEEDaRT_RT0_ + 165
      17  Realm                               0x0000000102aaee41 _ZN5realm5_impl18CollectionNotifier17for_each_callbackIZNS1_13after_advanceEvE3$_9EEvOT_ + 273
      18  Realm                               0x0000000102aaed29 _ZN5realm5_impl18CollectionNotifier13after_advanceEv + 25
      19  Realm                               0x0000000102ab1b88 _ZN5realm5_impl15NotifierPackage13after_advanceEv + 456
      20  Realm                               0x0000000102e0de72 _ZN12_GLOBAL__N_126advance_with_notificationsIZN5realm5_impl11transaction7advanceERKNSt3__110unique_ptrINS1_11SharedGroupENS4_14default_deleteIS6_EEEEPNS1_14BindingContextERNS2_15NotifierPackageEE3$_0EEvSD_SB_OT_SF_ + 1586
      21  Realm                               0x0000000102e0d82c _ZN5realm5_impl11transaction7advanceERKNSt3__110unique_ptrINS_11SharedGroupENS2_14default_deleteIS4_EEEEPNS_14BindingContextERNS0_15NotifierPackageE + 60
      22  Realm                               0x0000000102b415d1 _ZN5realm5_impl16RealmCoordinator16advance_to_readyERNS_5RealmE + 913
      23  Realm                               0x0000000102d766ce _ZN5realm5Realm6notifyEv + 862
      24  Realm                               0x0000000102e3f9cb _ZNK5realm5_impl17WeakRealmNotifier8CallbackclEv + 75
      25  Realm                               0x0000000102e4084c _ZZN5realm4util15EventLoopSignalINS_5_impl17WeakRealmNotifier8CallbackEEC1EOS4_ENKUlPvE_clES7_ + 28
      26  Realm                               0x0000000102e40828 _ZZN5realm4util15EventLoopSignalINS_5_impl17WeakRealmNotifier8CallbackEEC1EOS4_ENUlPvE_8__invokeES7_ + 24
      27  CoreFoundation                      0x00000001063ccc01 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
      28  CoreFoundation                      0x00000001063b20cf __CFRunLoopDoSources0 + 527
      29  CoreFoundation                      0x00000001063b15ff __CFRunLoopRun + 911
      30  CoreFoundation                      0x00000001063b1016 CFRunLoopRunSpecific + 406
      31  GraphicsServices                    0x000000010bda8a24 GSEventRunModal + 62
      32  UIKit                               0x00000001041220d4 UIApplicationMain + 159
      33  RealmTest                           0x00000001029c6d37 main + 55
      34  libdyld.dylib                       0x0000000106aad65d start + 1
      35  ???                                 0x0000000000000001 0x0 + 1
  )
  libc++abi.dylib: terminating with uncaught exception of type NSException
  </code></pre>
  
  <p>The code itself, is:</p>
  
  <pre><code>import UIKit
  import RealmSwift
  
  class Model: Object {
  
      dynamic var id: String = ""
      dynamic var text: String = ""
  
      override static func primaryKey() -&gt; String? {
  
          return "id"
      }
  }
  
  class ViewController: UIViewController {
  
      let realm = try! Realm()
      var results: Results&lt;Model&gt;?
  
      var token: NotificationToken!
  
      fileprivate lazy var queue: DispatchQueue = {
  
          return DispatchQueue(label: "realm")
      }()
  
      @IBOutlet weak var tableView: UITableView! {
          didSet {
              tableView.register(UITableViewCell.self, forCellReuseIdentifier: "UITableViewCell")
          }
      }
  
      override func viewDidLoad() {
          super.viewDidLoad()
  
          results = realm.objects(Model.self)
          token = results?.addNotificationBlock { changes in
  
              switch changes {
  
              case .initial(let objects):
                  print("Initial \(objects.count)")
  
              case .update(let objects, let deletions, let insertions, let modifications):
  
                  if !deletions.isEmpty {
  
                      let indexes = deletions.map({ "\($0)" }).joined(separator: ",")
                      print("\(objects.count) objects. Delete: \(indexes)")
                      print(deletions.map({ objects[$0] }))
                  }
  
                  if !insertions.isEmpty {
  
                      let indexes = insertions.map({ "\($0)" }).joined(separator: ",")
                      print("\(objects.count) objects. Insert: \(indexes)")
                      print(insertions.map({ objects[$0] }))
                  }
  
                  if !modifications.isEmpty {
  
                      let indexes = modifications.map({ "\($0)" }).joined(separator: ",")
                      print("\(objects.count) objects. Modify: \(indexes)")
                      print(insertions.map({ objects[$0] }))
                  }
  
                  self.tableView.reloadData()
  
              case .error(let error):
                  print(error.localizedDescription)
              }
          }
      }
  
      @IBAction func add(_ sender: UIButton) {
  
          let id = UUID().uuidString
          print("Add: \(id)")
  
          queue.async {
  
              let realm = try! Realm()
  
              let model = Model()
              model.id = id
  
              do {
  
                  try realm.write {
  
                      realm.add(model, update: true)
                  }
              }
              catch let error {
  
                  print(error.localizedDescription)
              }
          }
      }
  
      @IBAction func modify(_ sender: UIButton) {
  
          guard let model = realm.objects(Model.self).first else { return }
  
          let id = model.id
          print("Modify: \(id)")
  
          queue.async {
  
              let r = try! Realm()
  
              guard let object = r.object(ofType: Model.self, forPrimaryKey: id) else { return }
  
              do {
  
                  try r.write {
  
                      object.text = "\(Date().description)"
                  }
              }
              catch let error {
  
                  print(error.localizedDescription)
              }
          }
      }
  
      func delete(id: String) {
  
          print("Delete: \(id)")
  
          queue.async {
  
              let realm = try! Realm()
  
              guard let object = realm.object(ofType: Model.self, forPrimaryKey: id) else { return }
  
              do {
  
                  try realm.write {
  
                      realm.delete(object)
                  }
              }
              catch let error {
  
                  print(error.localizedDescription)
              }
          }
      }
  }
  
  extension ViewController: UITableViewDataSource {
  
      func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
  
          return results!.count
      }
  
  
      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
  
          guard let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell") else { fatalError() }
  
          cell.textLabel!.text = results?[indexPath.row].id
  
          return cell
      }
  }
  
  extension ViewController: UITableViewDelegate {
  
      func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  
          let object = results![indexPath.row]
  
          delete(id: object.id)
      }
  }
  </code></pre>
  
  <p><strong>Refinements</strong></p>
  
  <ul>
  <li>Removing the UITableView and reload aspect of the sample project does not fix the issue.</li>
  <li>Remove the write DispatchQueue and doing everything the main thread does not fix the issue.</li>
  </ul>