NSFetchedResultsController在错误的indexPath中添加项

时间:2017-06-13 16:23:45

标签: ios uitableview core-data swift3 nsfetchedresultscontroller

我写了简单的计数器app。它使用CoreData来存储数据。在模型中,我有一个名为" Counter"具有属性"值" (Int64)和"位置"(Int16)。第二个属性是tableView中的位置。用户可以添加,删除或增加计数器。我还使用NSFetchedResultsController来填充我的tableView。应用可行,但是当我,例如,添加5个计数器,更改其值,删除第二个和第三个值并添加新值时,计数器将不会插入到tableView的末尾(这里是视频{{ 3}})。我的代码出了什么问题?

import UIKit
import CoreData

class TableViewController: UITableViewController, NSFetchedResultsControllerDelegate {

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

var frc: NSFetchedResultsController<Counter> = {
    let fetchRequest: NSFetchRequest<Counter> = Counter.fetchRequest()
    let sortDescriptor = NSSortDescriptor(key: "position", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor]
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
    do {
        try frc.performFetch()
    } catch {
        print(error)
    }
    return frc
}()


@IBAction func addCounter(_ sender: UIBarButtonItem) {
    let counter = Counter(context: context)
    counter.value = 0
    counter.position = Int16(frc.fetchedObjects!.count)
    do {
        try context.save()
    } catch {
        print(error)
    }

}

@IBAction func longPressed(_ sender: UILongPressGestureRecognizer) {
    if sender.state == UIGestureRecognizerState.began {
        let touchPoint = sender.location(in: self.view)
        if let indexPath = tableView.indexPathForRow(at: touchPoint) {
            // your code here, get the row for the indexPath or do whatever you want
            let counter = frc.object(at: indexPath)
            counter.value = 0

            do {
                try context.save()
            } catch {
                print(error)
            }
        }
    }

}


override func viewDidLoad() {
    super.viewDidLoad()

    frc.delegate = self
}


// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {
    guard let sections = frc.sections?.count else {return 0}
    return sections
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    guard let sections = frc.sections else {return 0}
    return sections[section].numberOfObjects
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    let counter = frc.object(at: indexPath)
    cell.textLabel!.text! = String(counter.value)

    return cell
}

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

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
    switch type {
    case .insert:
        guard let indexPath = newIndexPath else {return}
        tableView.insertRows(at: [indexPath], with: .fade)
    case .delete:
        guard let indexPath = indexPath else {return}
        tableView.deleteRows(at: [indexPath], with: .fade)
    case .update:
        guard let indexPath = indexPath else {return}
        let cell = tableView.cellForRow(at: indexPath)
        let counter = frc.object(at: indexPath)
        cell?.textLabel?.text = String(counter.value)
    default:
        break
    }
}

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

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let counter = frc.object(at: indexPath)
    counter.value += Int64(1)

    do {try context.save()}
    catch {print(error)}

    tableView.deselectRow(at: indexPath, animated: true)
}

   // Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
            let counter = frc.object(at: indexPath)
            context.delete(counter)

        do {
            try context.save()
        } catch {
            print(error)
        }
    }
}

}

1 个答案:

答案 0 :(得分:-1)

您正在以错误的方式添加位置。 假设你有

A1,A2,A3,A4,A5

然后删除A2,A3

之后你就拥有了 A1,A4,A5

所以添加新的是B3,因为现在的数量是3 A1,B3,A4,A5

添加另一行变为B4,因此它可以在A4之前或之后占据任何位置。

此订单是由于仓位的排序顺序所致。

您可以通过获取最后一个获取的对象并增加位置和结果来解决此问题,然后将:

A1,A4,A5,B6,B7