2017-02-27 96 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之前,它也立即被調用。

我現在回到正軌!