领域addNotificationBlock给了我一个界限

时间:2017-06-01 04:43:33

标签: swift realm

对于我来说,这是一个非常间歇性的故障。我在几个罕见的场合看过它,但只有一次在开发过程中,而且仅在上个月左右。

有时,当我收到更改通知时,返回的对象数组为空,但修改列表中包含索引。

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)
}
  1. 此代码有什么根本原因吗?
  2. 这应该是安全的操作吗?
  3. 如果我防范这种情况,我会离开 与正在发生的变化同步?
  4. 这是一些重现的代码。只看到这个删除。

    我添加了一个UITableView和UIButtons来添加和修改。

    我不明白的是,当我删除一行时,删除打印为:

    (lldb) po deletions
    ▿ 2 elements
      - 0 : 6
      - 1 : 19
    

    此代码的输出是:

    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
    

    代码本身是:

    import UIKit
    import RealmSwift
    
    class Model: Object {
    
        dynamic var id: String = ""
        dynamic var text: String = ""
    
        override static func primaryKey() -> String? {
    
            return "id"
        }
    }
    
    class ViewController: UIViewController {
    
        let realm = try! Realm()
        var results: Results<Model>?
    
        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) -> Int {
    
            return results!.count
        }
    
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> 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)
        }
    }
    

    加细

    • 删除示例项目的UITableView并重新加载方面无法解决问题。
    • 删除写入DispatchQueue并执行主线程无法解决问题的所有内容。

0 个答案:

没有答案