从CoreData

时间:2017-12-15 06:11:58

标签: ios swift core-data uiview

我有一个简单的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
    }
}

这是一个单元格:

enter image description here

修改 这是保存/更新方法,从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
    }
}

1 个答案:

答案 0 :(得分:3)

更新时尝试

tableView.reloadRows(at: [indexPath], with: .automatic)

而不是

let cell = tableView.cellForRow(at: indexPath) as! TaskCell
            cell.viewModel = viewModel.getTaskCell(indexPath: indexPath)

我希望这会奏效。