2017-02-27 66 views
0

在选择NSFetchedResultsController(FRC)中的一行时,我的应用程序允许通过细分视图控制器来更改细节。保存更改后,编辑的行将返回并插入到FRC中。更新FRC后TableViewController不刷新

.update代码被触发在以下switch

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { 
    switch type { 
    case .update: 
     configureCell(cell: tableView.cellForRow(at: indexPath! as IndexPath)!, indexPath: indexPath! as NSIndexPath) 
     tableView.reloadRows(at: [indexPath!], with: .automatic) 
    case .insert: 
     tableView.insertRows(at: [newIndexPath!], with: .automatic) 
    case .delete: 
     tableView.deleteRows(at: [indexPath!], with: .automatic) 
    case .move: 
     tableView.moveRow(at: indexPath! as IndexPath, to: newIndexPath! as IndexPath) 
    } 
} 

configureCell()方法是:

func configureCell(cell: UITableViewCell, indexPath: NSIndexPath) { 
    var handicap: Float 

    let cellIdentifier = "PlayerTableViewCell" 

    guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath as IndexPath) as? PlayerTableViewCell else { 
      fatalError("The dequeued cell is not an instance of PlayerTableViewCell") 
     } 

    // Populate cell from the NSManagedObject instance 
    guard let player = fetchedResultsController.object(at: indexPath as IndexPath) as? Golfer else { 
     fatalError("Unexpected Object in FetchedResultsController") 
    } 

    let firstName = player.value(forKey: "firstName") as! String? 
    let lastName = player.value(forKey: "lastName") as! String? 
    let fullName = firstName! + " " + lastName! 
    handicap = player.value(forKey: "exactHandicap") as! Float 

    cell.playerFullName?.text = fullName 

    cell.playerPhoto.image = UIImage(data: player.value(forKey: "photo") as! Data) 

    cell.numExactHandicap.text = "\(Int(handicap))" 
    cell.numStrokesReceived.text = "\(handicap.cleanValue)" 

    print("Object for configuration: \(player)") 
} 

,其细胞的类定义是:

class PlayerTableViewCell: UITableViewCell { 

    //MARK: Properties 
    @IBOutlet weak var playerFullName: UILabel! 
    @IBOutlet weak var playerPhoto: UIImageView! 
    @IBOutlet weak var exactHandicapLabel: UILabel! 
    @IBOutlet weak var strokesReceivedLabel: UILabel! 
    @IBOutlet weak var numExactHandicap: UILabel! 
    @IBOutlet weak var numStrokesReceived: UILabel! 

    override func awakeFromNib() { 
     super.awakeFromNib() 
     // Initialization code 
    } 

    override func setSelected(_ selected: Bool, animated: Bool) { 
     super.setSelected(selected, animated: animated) 

     // Configure the view for the selected state 
    } 

}

- 编辑#1 -

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    // Table view cells are reused and should be dequeued using a cell identifier 
    let cell = tableView.dequeueReusableCell(withIdentifier: "PlayerTableViewCell", for: indexPath) 

    configureCell(cell: cell, indexPath: indexPath as NSIndexPath) 

    return cell 
} 

我得到的行为在许多方面意外。

  1. 屏幕上的数据不更新后的.update代码的处理中,保持在FRC预编辑的值。

  2. 只有当我在表格中选择同一行时才进行行刷新。即它会显示旧值,但在再次启动编辑行之前,我会再次选择该行时更改为新值。

  3. 当我第一次选择除第0行以外的任何行时,它将单元格中的所有值设置为故事板中显示的默认值。但是,在任何情况下,行0 从未更改之前的变化。

任何见解非常欢迎!

- 编辑#3月” 20,2017年 -

我一直在小打小闹,在这个问题上一段时间。核心问题仍然存在 - 在处理.update代码后屏幕上的数据不会刷新,从而在FRC中保留预编辑的值。

的关键代码段现在这个样子:

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { 
    switch type { 
    case .update: 
     golferView.reloadRows(at: [indexPath!], with: .automatic) 
    case .insert: 
     golferView.insertRows(at: [newIndexPath!], with: .automatic) 
    case .delete: 
     golferView.deleteRows(at: [indexPath!], with: .automatic) 
    case .move: 
     golferView.moveRow(at: indexPath! as IndexPath, to: newIndexPath! as IndexPath) 
    } 
} 

func configureCell(cell: UITableViewCell, indexPath: NSIndexPath) { 
    var handicap: Float 
    var player: Golfer 

    let cellIdentifier = "PlayerTableViewCell" 

    guard let cell = golferView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath as IndexPath) as? PlayerTableViewCell else { 
     fatalError("The dequeued cell is not an instance of PlayerTableViewCell") 
    } 

    // Populate cell from the NSManagedObject instance 
    player = fetchedResultsController.object(at: indexPath as IndexPath) 

    let firstName = player.value(forKey: "firstName") as! String? 
    let lastName = player.value(forKey: "lastName") as! String? 
    let fullName = firstName! + " " + lastName! 
    handicap = player.value(forKey: "exactHandicap") as! Float 

    cell.playerFullName?.text = fullName 

    cell.playerPhoto.image = UIImage(data: player.value(forKey: "photo") as! Data) 

    cell.numExactHandicap.text = "\(Int(handicap))" 
    cell.numStrokesReceived.text = "\(handicap.cleanValue)" 

    print("Object for configuration: \(player). And cell values are = \(String(describing: cell.playerFullName?.text)), \(String(describing: cell.numExactHandicap.text)), \(String(describing: cell.numStrokesReceived.text))") 
} 

我已经验证controller()方法正确烧制,而且.update开关点火reloadRows。这反过来激发了configureCell(),其中来自FRC的返回行的内容是正确的,并且插入到单元中的值与从FRC返回的值匹配。它只是不会刷新用户界面。

+1

你确定你的更新代码被调用?另外,你不需要同时调用'configureCell'和'reloadRows'。 “你编辑的行被返回并插入到FRC中”是什么意思?这是一个新的行被创建(而不是更新)? –

+0

嗨戴夫。按顺序: 1.是的,'.update'代码被调用。当我在那里设置一个断点时,它会停下来,让我穿过。 2.如果我注释掉对'reloadRows'的调用,那么行为会发生变化。而不是显示原始的,预编辑的行内容,它现在将行的内容重置为默认的故事板值。调用'reloadRows'会填充表中的过期行,而不是我想要的更新值。 3.我的意思是我希望编辑后的细节反映为FRC中原始行的更新。 – Dave

+0

2.我的意思是你应该删除'configureCell'方法调用,因为这将通过重新加载该行自动调用。 –

回答

1

在调查内存使用问题时,我偶然发现dequeueReusableCell重复调用,修复后解决了我遇到的问题。

在我的文章中,dequeueReusableCell被称为configureCell。在调用override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell调用configureCell之前,它也立即被调用。

我现在回到正轨!