我有一个简单的Todo应用程序。在主屏幕中,我显示可用任务列表,每个单元格显示一个小的UIView,用于类别颜色,类别名称,标题和日期。在第一次启动时,所有数据显示为correnct,但是当我选择其中一个进行更新并使用另一个类别的颜色更改类别并保存CoreData中的更改时,模态视图(我更新数据的地方)消失,NSFetchedResultController获取新数据以填充tableView,所有数据更改,但只有颜色保持在更新之前。注意:当窗口消失时,单元格在我更新后首先显示正确的颜色,然后在第二次更改为旧的颜色。我调试了应用程序,调试器show,从CoreData获取的正确和新数据,一切都必须正确呈现,但UIView的背景颜色是错误的。
这是我的手机代码:
@IBOutlet weak var title: UILabel!
@IBOutlet weak var category: UILabel!
@IBOutlet weak var date: UILabel!
@IBOutlet weak var progress: UILabel!
@IBOutlet weak var categoryColorView: UIView!
override func awakeFromNib() {
super.awakeFromNib()
}
var viewModel: TaskCellViewModel! {
didSet {
title.text = viewModel.title
category.text = viewModel.categoryName
date.text = convert()
progress.text = viewModel.isDone ? "Done" : "In Progress"
progress.textColor = viewModel.isDone ? UIColor.green : UIColor.red
categoryColorView.backgroundColor = Constants.colors[viewModel.categoryColor]!.color
}
}
这是一个单元格:
修改 这是保存/更新方法,从NewTaskViewModel调用:
func save(completion: @escaping (AppResult<Task>) -> Void) {
let context = CustomContext.shared.getContext
do {
if _task.id != "" {
let taskFetchRequest: NSFetchRequest<TaskEntity> = TaskEntity.fetchRequest()
taskFetchRequest.predicate = NSPredicate(format: "id == %@", _task.id)
let taskEntity = try context.fetch(taskFetchRequest).first!
taskEntity.title = task.title
taskEntity.date = task.date as NSDate?
taskEntity.content = task.content
taskEntity.isDone = task.isDone
let categoryFetchRequest: NSFetchRequest<CategoryEntity> = CategoryEntity.fetchRequest()
categoryFetchRequest.predicate = NSPredicate(format: "name == %@", _task.category.name)
taskEntity.category = try context.fetch(categoryFetchRequest).first!
} else {
let taskEntity = TaskEntity(context: context)
taskEntity.id = UUID().uuidString
taskEntity.title = task.title
taskEntity.date = task.date as NSDate?
taskEntity.content = task.content
taskEntity.isDone = task.isDone
let categoryFetchRequest: NSFetchRequest<CategoryEntity> = CategoryEntity.fetchRequest()
categoryFetchRequest.predicate = NSPredicate(format: "name == %@", _task.category.name)
taskEntity.category = try context.fetch(categoryFetchRequest).first!
}
try context.save()
completion(.success(task))
} catch {
completion(.error(error.localizedDescription))
}
}
这是NewTaskViewController的保存/更新调用(模态视图):
@IBAction func save(_ sender: UIBarButtonItem) {
switch viewModel.validation() {
case .success(_):
viewModel.save { result in
switch result {
case .success(_):
DispatchQueue.main.async { [unowned self] in
self.dismiss(animated: true, completion: nil)
}
case .error(let error):
DispatchQueue.main.async { [unowned self] in
self.errorAlert(withMessage: error)
}
}
}
case .error(let errorMsg):
DispatchQueue.main.async { [unowned self] in
self.errorAlert(withMessage: errorMsg)
}
}
}
tableView的cellForRowAt:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Constants.taskCell, for: indexPath) as! TaskCell
cell.viewModel = viewModel.getTaskCell(indexPath: indexPath)
return cell
}
getTaskCell:
func getTaskCell(indexPath: IndexPath) -> TaskCellViewModel {
let taskEntity = fetchedResultsController.object(at: indexPath)
return TaskCellViewModel(withTask: taskEntity.convertToModel())
}
taskEntity.convertToModel()
@NSManaged public var id: String?
@NSManaged public var content: String?
@NSManaged public var date: NSDate?
@NSManaged public var isDone: Bool
@NSManaged public var title: String?
@NSManaged public var category: CategoryEntity?
func convertToModel() -> Task {
var task = Task()
task.id = self.id!
task.title = self.title!
task.content = self.content!
task.isDone = self.isDone
task.date = self.date! as Date
task.category.name = self.category!.name!
task.category.color = Constants.colors[self.category!.color!]!
return task
}
和NSFetchedResultControllerDelegates的:
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .insert:
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .fade)
}
break
case .update:
if let indexPath = indexPath {
let cell = tableView.cellForRow(at: indexPath) as! TaskCell
cell.viewModel = viewModel.getTaskCell(indexPath: indexPath)
}
break
case .delete:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
break
default:
break
}
}
答案 0 :(得分:3)
更新时尝试
tableView.reloadRows(at: [indexPath], with: .automatic)
而不是
let cell = tableView.cellForRow(at: indexPath) as! TaskCell
cell.viewModel = viewModel.getTaskCell(indexPath: indexPath)
我希望这会奏效。