使用coredata时,tableview.reloaddata()在搜索栏取消按钮后无效

时间:2017-12-03 10:02:58

标签: swift uitableview

我是swift的新手。我正在使用tableviewcontroller并使用核心数据来显示我的搜索结果。搜索按钮工作正常,这是正确的但每当我点击取消按钮它显示我空屏幕。我打印了项目数量。它达到所需的计数并重置为零。我看了很多答案,但我还没有找到对我有用的东西。我正在使用自定义单元格,甚至在点击搜索后它会显示搜索字符串的结果。

 class CoinViewController: UITableViewController,UISearchResultsUpdating, UISearchBarDelegate {

let searchController = UISearchController(searchResultsController: nil)
lazy var fetchedResultController: NSFetchedResultsController<NSFetchRequestResult> = {
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: Coin.self))
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "coinName", ascending: true)]
    let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: CoreDataStack.sharedInstance.persistentContainer.viewContext, sectionNameKeyPath: nil, cacheName: nil)
    frc.delegate = self
    return frc
}()

override func viewDidLoad() {
    super.viewDidLoad()
    self.getData()
    self.navigationItem.title = "Coin List"
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.reloadData()
    searchController.searchBar.delegate = self

    searchController.searchResultsUpdater = self
    searchController.dimsBackgroundDuringPresentation = false
    definesPresentationContext = true
}
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}



private func createCoinEntityFrom(dictionary: [String: AnyObject]) -> NSManagedObject? {
    let service = ApiService()
    let context = CoreDataStack.sharedInstance.persistentContainer.viewContext
    if let coinEntity = NSEntityDescription.insertNewObject(forEntityName: "Coin", into: context) as? Coin {
        coinEntity.algorithm = dictionary["Algorithm"] as? String
        coinEntity.coinName = dictionary["CoinName"] as? String
        if let imageURL = dictionary["ImageUrl"] as? String {
            coinEntity.imageURL = (service.baseImageurl) + imageURL
        }
        coinEntity.totalCoinSupply = dictionary["TotalCoinSupply"] as? String
        return coinEntity
    }
    return nil
}

private func saveInCoreDataWith(array: [String: AnyObject]) {
    _ = array.map{self.createCoinEntityFrom(dictionary: $1 as! [String : AnyObject])}
    do {
        try CoreDataStack.sharedInstance.persistentContainer.viewContext.save()
    } catch let error {
        print(error)
    }
}

private func clearData() {
    do {

        let context = CoreDataStack.sharedInstance.persistentContainer.viewContext
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: Coin.self))
        do {
            let objects  = try context.fetch(fetchRequest) as? [NSManagedObject]
            _ = objects.map{$0.map{context.delete($0)}}
            CoreDataStack.sharedInstance.saveContext()
        } catch let error {
            print("ERROR DELETING : \(error)")
        }
    }
}

func showAlertWith(title: String, message: String, style: UIAlertControllerStyle = .alert) {
    let alertController = UIAlertController(title: title, message: message, preferredStyle: style)
    let action = UIAlertAction(title: title, style: .default) { (action) in
        self.dismiss(animated: true, completion: nil)
    }
    alertController.addAction(action)
    self.present(alertController, animated: true, completion: nil)
}

func getData() {

    do {
        try self.fetchedResultController.performFetch()
        print("COUNT FETCHED FIRST: \(self.fetchedResultController.sections?[0].numberOfObjects)")
    } catch let error  {
        print("ERROR: \(error)")
    }


    let service = ApiService()
    service.getDataWith { (result) in
        switch result {
        case .Success(let data):
            //                for item in data {
            //                    self.coin.append(item as! Coin)
            //                }
            self.clearData()
            self.saveInCoreDataWith(array: data)
        case .Error(let message):
            DispatchQueue.main.async {
                self.showAlertWith(title: "Error", message: message)
            }
        }
    }
}


func updateSearchResults(for searchController: UISearchController) {


    search(searchController.searchBar.text!)
}



func search(_ searchText: String, scope: String="All") {

    var predicate:NSPredicate? = nil
    let searchBar = searchController.searchBar
    if (searchBar.text != nil) {
        predicate = NSPredicate(format: "(coinName contains [cd] %@) ", searchBar.text!, searchBar.text!)
    }
    self.fetchedResultController.fetchRequest.predicate = predicate
    do {
        try self.fetchedResultController.performFetch()
    } catch let error  {
        print("ERROR: \(error)")
    }
    tableView.reloadData()

}

func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {

    if let searchTextField = searchController.searchBar.value(forKey: "_searchField") as? UITextField {
        searchTextField.clearButtonMode = .always
    }

}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {

    UIView.animate(withDuration: 0.3, animations: { () -> Void in
        searchBar.removeFromSuperview()
        self.tableView.tableHeaderView = nil
        searchBar.showsCancelButton = false
        searchBar.resignFirstResponder()

        self.fetchedResultController.fetchRequest.predicate = nil
        do {
            try self.fetchedResultController.performFetch()
            print("COUNT FETCHED FIRST: \(self.fetchedResultController.sections?[0].numberOfObjects)")

        } catch let error  {
            print("ERROR: \(error)")
        }
        self.tableView.reloadData()
    }, completion: { finished in
        self.navigationController!.navigationBar.alpha = 1
        self.navigationController!.isNavigationBarHidden = false
    })
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    if let count = fetchedResultController.sections?.first?.numberOfObjects {
        print("----> \(count)")
        return count
    }
    return 1
}

override func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CoinCell", for: indexPath)
        as! CoinCell
    if let coin = fetchedResultController.object(at: indexPath) as? Coin {
        cell.coinNameLabel.text = coin.coinName
        cell.coinValueLabel.text = coin.totalCoinSupply! + "$"
        cell.coinImageUrl?.downloadImage(from: coin.imageURL!)
        cell.percentageShift.text = "+12.56%"
    }
    return cell
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 120
}

@IBAction func searchFilter( _ sender: UIBarButtonItem) {
    tableView.tableHeaderView = searchController.searchBar
    searchController.searchBar.becomeFirstResponder()
}

} 扩展CoinViewController:NSFetchedResultsControllerDelegate {     func控制器(_ controller:NSFetchedResultsController,didChange anObject:Any,at indexPath:IndexPath?,type:NSFetchedResultsChangeType,newIndexPath:IndexPath?){

    switch type {
    case .insert:
        self.tableView.insertRows(at: [newIndexPath!], with: .automatic)
    case .delete:
        self.tableView.deleteRows(at: [indexPath!], with: .automatic)
    default:

        break
    }
}

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    self.tableView.endUpdates()
}

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    tableView.beginUpdates()
}

}

1 个答案:

答案 0 :(得分:0)

这是在取消搜索时告诉您的功能:

func searchBarCancelButtonClicked(_ searchBar: UISearchBar)

如果过滤了结果,则应重新加载它们并再次调用 reloadData()

修改
我认为这很清楚,但既然你在这里要求完整的代码,那就是:

func searchBarCancelButtonClicked(_ searchBar: UISearchBar)
{
    self.fetchedResultController.fetchRequest.predicate = nil
    do {
        try self.fetchedResultController.performFetch()
        tableView.reloadData()
    } catch let error  {
        print("ERROR: \(error)")
    }
}

这样您可以在不过滤结果的情况下再次获取结果,然后重新加载表视图。