У меня есть приложение iOS ToDo, основанное на разработке приложений iBook с Swift. Я расширил его, чтобы использовать CoreData (чтобы иметь возможность сортировать по дате). Я также добавил функцию зачеркивания taskTitleLabel при переключении кнопки isCompleteButton. Кажется, что все работает нормально, пока последний элемент в табличном представлении не будет завершен, а затем не завершен. Если новый элемент добавляется в список после переключенного, к заголовку применяется зачеркивание без выбора isCompleteButton. Вот код:
TaskCell.swift
import UIKit
@objc protocol TaskCellDelegate: class {
func checkmarkTapped(sender: TaskCell)
}
class TaskCell: UITableViewCell {
var delegate: TaskCellDelegate?
@IBOutlet weak var isCompleteButton: UIButton!
@IBOutlet weak var taskTitleLabel: UILabel!
@IBAction func isCompleteButtonTapped(_ sender: UIButton) {
delegate?.checkmarkTapped(sender: self)
}
override func prepareForReuse() {
super.prepareForReuse()
isCompleteButton.isSelected = !isCompleteButton.isSelected
}
}
TasksTableViewController
...
func checkmarkTapped(sender: TaskCell) {
if let indexPath = tableView.indexPath(for: sender){
let task = fetchedResultsController.object(at: indexPath) as? Task
task?.isComplete = !task!.isComplete
coreDataStack.saveContext()
}
}
...
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell") as? TaskCell else { fatalError("Could not dequeue a celL")}
cell.delegate = self
let task = fetchedResultsController.object(at: indexPath) as! Task
cell.taskTitleLabel.text = task.title
cell.isCompleteButton.isSelected = task.isComplete
if task.isComplete {
let strikeThroughTask = NSMutableAttributedString(string: task.title!)
strikeThroughTask.addAttributes([
NSAttributedString.Key.strikethroughStyle: NSUnderlineStyle.single.rawValue,
NSAttributedString.Key.strikethroughColor: UIColor.darkGray,
NSAttributedString.Key.font : UIFont.systemFont(ofSize: 12.0)
], range: NSMakeRange(0, strikeThroughTask.length))
cell.taskTitleLabel.attributedText = strikeThroughTask
}
if task.hasDueDate {
if task.dueDate! < Date().startOfDay {
cell.taskTitleLabel.textColor = .red
} else if task.dueDate! > Date().startOfDay && task.dueDate! < Date().endOfDay {
if #available(iOS 13.0, *) {
cell.taskTitleLabel.textColor = .label
} else {
// Fallback on earlier versions
cell.taskTitleLabel.textColor = .black
}
} else {
// future due date
cell.taskTitleLabel.textColor = UIColor(red: 100/255.0, green: 100/255.0, blue: 100/255.0, alpha: 1)
}
} else {
//no dueDate
cell.taskTitleLabel.textColor = UIColor(red: 125/255.0, green: 125/255.0, blue: 125/255.0, alpha: 1)
}
return cell
}
Я также использую NSFetchResultsController
extension TasksTableViewController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
let index = indexPath ?? (newIndexPath ?? nil)
guard let cellIndex = index else { return }
switch type {
case .insert:
tableView.insertRows(at: [cellIndex], with: .automatic)
case .delete:
tableView.deleteRows(at: [cellIndex], with: .automatic)
case .update:
tableView.reloadRows(at: [cellIndex], with: .automatic)
default:
break
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
}
Из AddTaskTableViewController
...
func updateTaskEntry() {
guard let task = task else { return }
task.title = taskTitleTextField.text
task.isComplete = isCompleteButton.isSelected
task.hasDueDate = hasDueDateSwitch.isOn
if hasDueDateSwitch.isOn {
task.dueDate = dueDatePicker.date
} else {
task.dueDate = nil
}
task.notes = notesTextView.text
coreDataStack.saveContext()
}
@IBAction func saveButtonTapped(_ sender: UIBarButtonItem) {
}
func saveNewTask() {
let task = Task(context: coreDataStack.managedObjectContext)
task.title = taskTitleTextField.text
task.isComplete = isCompleteButton.isSelected
task.hasDueDate = hasDueDateSwitch.isOn
if hasDueDateSwitch.isOn {
task.dueDate = dueDatePicker.date
} else {
task.dueDate = nil
}
task.notes = notesTextView.text
task.createdOn = Date()
coreDataStack.saveContext()
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
guard segue.identifier == "saveUnwind" else {return}
if navigationItem.title == "Add Task" {
saveNewTask()
} else if navigationItem.title == "Update Task" {
updateTaskEntry()
}
}
}
Итак, мой вопрос: почему текст в заголовке метки имеет зачеркнутый текст без выделенной кнопки isCompleteButton или task.isComplete? Чего мне не хватает?