Roobiq / RBQFetchedResultsController

Drop-in replacement for NSFetchedResultsController backed by Realm.
MIT License
476 stars 70 forks source link

Swift3 no notification passed to the delegate #110

Closed wieseljonas closed 7 years ago

wieseljonas commented 7 years ago

I'm using the RBQFetchedResultsControllerDelegate in swift3 but it the controller doesn't get notified of realm changes now

Anyone having a similar issue?

open var realmConfiguration: Realm.Configuration {
    set { self.internalConfiguration = newValue }
    get {
        if let configuration = self.internalConfiguration { return configuration }
        return Realm.Configuration.defaultConfiguration
    }
}

open var realm: Realm {
    return try! Realm()
}

 fileprivate lazy var fetchedResultsController: RBQFetchedResultsController = {
    let controller = RBQFetchedResultsController()
    return controller
}()

fileprivate var rlmRealm: RLMRealm {
    let configuration = self.toRLMConfiguration(self.realmConfiguration)
    return try! RLMRealm(configuration: configuration)
}

fileprivate let searchQueue: OperationQueue = {
    let queue = OperationQueue()
    queue.maxConcurrentOperationCount = 1
    return queue
}()

override func viewDidLoad() {
    super.viewDidLoad()        
    tableView = UITableView()
    tableView.delegate = self
    tableView.rowHeight = 60
    tableView.register(MakoListCell.classForCoder(), forCellReuseIdentifier: "MakoListCell")
    searchBar = UISearchBar()
    searchBar.delegate = self
    searchBar.sizeToFit()
    view.addSubview(tableView)
    tableView.tableHeaderView = searchBar
    tableView.fillSuperview()
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    if tableView.dataSource == nil  {
        tableView.dataSource = self
    }
    reloadDataFetch()
}

func reloadDataFetch(){
    let searchString = searchBar.text
    let searchOperation = BlockOperation { [weak self] () -> Void in
        if let strongSelf = self {
            strongSelf.updateFetchedResultsControllers(searchString)
        }
    }
    self.searchQueue.cancelAllOperations()
    self.searchQueue.addOperation(searchOperation)
}

fileprivate func updateFetchedResultsControllers(_ searchString:String?) {
    objc_sync_enter(self)
   if let fetchRequest = self.searchFetchRequest("Individual", predicate: searchPredicateIndividuals(searchString), sortPropertyKey: "lowercaseName", sortAscending: true) {
            self.fetchedResultsController.updateFetchRequest(fetchRequest, sectionNameKeyPath: nil, andPerformFetch: true)
        }

    if self.isViewLoaded {
        self.runOnMainThread({ [weak self] () -> Void in
            print("reloading data")
            self?.tableView.reloadData()
            })
    }
    objc_sync_exit(self)
}

fileprivate func searchPredicateIndividuals(_ text: String?) -> NSPredicate? {
    if (text != "" &&  text != nil) {
        return NSPredicate(format: "NOT(status == 'deleted' || status == 'merged') AND NOT(lowercaseName == '') AND (lowercaseName CONTAINS[c] '\(text!)' OR (ANY emailAddresses.value CONTAINS[c] '\(text!)'))")
    }
    return NSPredicate(format: "NOT(status == 'deleted' || status == 'merged') AND NOT(lowercaseName == '')")
}
 @objc(tableView:cellForRowAtIndexPath:) public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let cell = tableView.dequeueReusableCell(withIdentifier: "MakoListCell", for: indexPath) as! MakoListCell
     cell.individual = i
     return cell
}

 @objc(tableView:commitEditingStyle:forRowAtIndexPath:) public func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
     let cell = tableView.cellForRow(at: indexPath) as! MakoListCell
     try! self.realm.write({ () -> Void in
            let i = cell.individual!
            cell.individual = nil
            self.realm.delete(i)
     })
}

func controller(_ controller: RBQFetchedResultsController, didChangeSection section: RBQFetchedResultsSectionInfo, at sectionIndex: UInt, for type: NSFetchedResultsChangeType) {

    let tableView = self.tableView
    if type == NSFetchedResultsChangeType.insert {
        let indexSet = IndexSet(integer: Int(sectionIndex))
        tableView?.insertSections(indexSet, with: UITableViewRowAnimation.fade)
    }
    else if type == NSFetchedResultsChangeType.delete {
        let indexSet = IndexSet(integer: Int(sectionIndex))
        tableView?.deleteSections(indexSet, with: UITableViewRowAnimation.fade)
    }

}

func controllerDidChangeContent(_ controller: RBQFetchedResultsController) {
    self.tableView.endUpdates()
}

func controllerWillChangeContent(_ controller: RBQFetchedResultsController) {
    self.tableView.beginUpdates()
}

func controller(_ controller: RBQFetchedResultsController, didChange anObject: RBQSafeRealmObject, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
    let tableView = self.tableView
    switch type {
    case .insert:
        tableView?.insertRows(at: [newIndexPath!], with: UITableViewRowAnimation.fade)
    case .delete:
        tableView?.deleteRows(at: [indexPath!], with: UITableViewRowAnimation.fade)
    case .update:
        tableView?.reloadRows(at: [indexPath!], with: UITableViewRowAnimation.fade)
    case .move:
        tableView?.deleteRows(at: [indexPath!], with: UITableViewRowAnimation.fade)
        tableView?.insertRows(at: [newIndexPath!], with: UITableViewRowAnimation.fade)
    }
}
bigfish24 commented 7 years ago

This was fixed in: https://github.com/Roobiq/RBQFetchedResultsController/releases/tag/v5.0.0