NSFetchedResultsController
(FRC)の行を選択するとき、私のアプリケーションでは、詳細ビューコントローラに分割することによって詳細を変更することができます。変更を保存した後、編集された行が返され、FRCに挿入されます。FRCが更新された後にTableViewControllerが更新されない
.update
コードは以下switch
にトリガされる:
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)")
}
および細胞クラス定義は次のとおり:
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()
方法がある
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
}
}
- EDIT#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
}
私が得る行動は、いくつかの方法で予想外のことです。
オンスクリーンデータはFRCに事前編集した値を保持し、
.update
コードの処理に続いて更新されません。テーブル内の同じ行を選択した場合にのみ、行が更新されます。私。古い値が表示されますが、瞬時に新しい値に変更されます。編集した行を再度起動する前に、行を再度選択します。
行0以外の行を初めて選択すると、セル内のすべての値がストーリーボードに表示されているデフォルト値に設定されます。ただし、ロー0 は決してに変更されます。
洞察力は大歓迎です!
- EDIT#3 [4月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から返された値と一致します。 UIを更新するだけではありません。
更新コードが呼ばれていますか?また、 'configureCell'と' reloadRows'の両方を呼び出す必要はありません。そして、「編集された行が返され、FRCに挿入された」ということはどういう意味ですか?新しい行が作成されていますか(更新ではありません)? –
こんにちは。順序: 1.はい、 '.update'コードが呼び出されています。私がそこにブレークポイントを設定すると、それが止まり、私はステップインすることができます。 2. 'reloadRows'の呼び出しをコメントアウトすると、動作が変わります。あらかじめ編集された元の行の内容を表示するのではなく、行の内容をデフォルトのストーリーボードの値にリセットします。 'reloadRows'を呼び出すと、私が必要とする更新された値ではなく、古い行がテーブルに取り込まれます。 3.私は、編集した詳細をFRCの元の行への更新として反映させたいということです。 – Dave
2. 'configureCell'メソッド呼び出しを削除する必要があるということは、その行をリロードして自動的に呼び出されるためです。 –