Я пытаюсь создать список дел, используя основные данные для сохранения данных, как из массива элементов контроллера представления категорий, так и из соответствующего массива элементов категории.Я устанавливаю связь между сущностями, чтобы при выборе категории из корневого контроллера выполнялся переход к соответствующему списку предметов.Все работает нормально .... но фильтр из контроллера элементов работает не так, как ожидалось, когда наберите в строке поиска нужный элемент для поиска, он возвращает только первый элемент, независимо от того, какое слово нужно было отфильтровать.Я не знаю, где это может быть, если кто-то может помочь, я буду очень признателен.
Я уже пытался модифицировать методы Delegate любым доступным мне способом, поэтому у меня довольно много идей.
** ToDoListVC
importUIKit импортирует CoreData
класс ToDoListViewController: UITableViewController {
var toDoItemArray = [ToDoItem]()
var selectedCategory : Category? {
didSet{
loadItems()
}
}
@IBOutlet weak var searchBar: UISearchBar!
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
print (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask))
searchBar.delegate = self
let tapGesture = UITapGestureRecognizer(target: self, action: #selector (tableViewTapped))
tableView.addGestureRecognizer(tapGesture)
// Do any additional setup after loading the view, typically from a nib.
tableView.register(UINib(nibName: "CustomToDoItemCell", bundle: nil), forCellReuseIdentifier: "CustomToDoItemCell")
}
//MARK - TableView DataSource Methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return toDoItemArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomToDoItemCell", for: indexPath) as! CustomToDoItemCell
let item = toDoItemArray[indexPath.row]
cell.toDoBodyText?.text = item.itemText
cell.toDoBodyText = UILabel(frame: CGRect(x: 16, y: 11, width: 160, height: 21))
cell.accessoryType = item.doneStatus == true ? .checkmark : .none
return cell
}
//MARK: - TableView Delegate Methods
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(toDoItemArray[indexPath.row])
//context.delete(toDoItemArray[indexPath.row])
//toDoItemArray.remove(at: indexPath.row)
toDoItemArray[indexPath.row].doneStatus = !toDoItemArray[indexPath.row].doneStatus
self.saveItems()
tableView.deselectRow(at: indexPath, animated: true)
}
//MARK: - Add New Items
@IBAction func addNewToDo(_ sender: UIBarButtonItem) {
var textField = UITextField()
let alert = UIAlertController(title: "Add A New Check-o Item", message: "", preferredStyle: .alert)
let addNewAction = UIAlertAction(title: "Add New To Do", style: .default) { (addNewAction) in
let newItem = ToDoItem(context: self.context)
newItem.itemText = textField.text!
newItem.doneStatus = false
newItem.parentCategory = self.selectedCategory
self.toDoItemArray.append(newItem)
self.saveItems()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (cancelAction) in
self.dismiss(animated: true, completion: nil)
self.tableView.reloadData()
}
alert.addTextField { (alertTextField) in
alertTextField.placeholder = "Start Typing Your New To Do"
textField = alertTextField //Extending the scope of the alert Text Field
}
alert.addAction(cancelAction)
alert.addAction(addNewAction)
present(alert, animated: true, completion: nil)
}
//MARK: - Creating & Reading Core Data
func saveItems () {
do {
try context.save()
} catch {
print ("Error saving context \(error)")
}
tableView.reloadData() //This method reloads data so the new item from the text field alert is added to the To Do Item Array
}
func loadItems (with request : NSFetchRequest<ToDoItem> = ToDoItem.fetchRequest(), predicate : NSPredicate? = nil) {
let categoryPredicate = NSPredicate(format: "parentCategory.categoryName MATCHES %@", selectedCategory!.categoryName!)
if let additionalPredicate = predicate {
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [categoryPredicate, additionalPredicate])
} else {
request.predicate = categoryPredicate
}
do {
toDoItemArray = try context.fetch(request)
} catch {
print ("Error Fetching Data From Context \(error)")
}
tableView.reloadData()
}
}
// MARK: - Методы делегата панели поиска
расширение ToDoListViewController: UISearchBarDelegate {
@objc func tableViewTapped() {
searchBar.endEditing(true)
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
let request : NSFetchRequest = ToDoItem.fetchRequest()
let predicate = NSPredicate(format: "itemText CONTAINS[cd] %@", searchBar.text!)
request.sortDescriptors = [NSSortDescriptor(key: "itemText", ascending: true)]
loadItems(with: request, predicate: predicate)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String){
if searchBar.text?.count == 0 {
loadItems()
DispatchQueue.main.async {
searchBar.resignFirstResponder()
}
}
}
}
** CategoryViewController
import UIKit import CoreData
class CategoryViewController: UITableViewController {
var categoryArray = [Category]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
print (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask))
loadItems()
tableView.register(UINib(nibName: "CustomToDoItemCell", bundle: nil), forCellReuseIdentifier: "CustomToDoItemCell")
}
//MARK: - TableView DataSource Methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return categoryArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomToDoItemCell", for: indexPath) as! CustomToDoItemCell
let item = categoryArray[indexPath.row]
cell.toDoBodyText?.text = item.categoryName
cell.toDoBodyText = UILabel(frame: CGRect(x: 16, y: 11, width: 160, height: 21))
return cell
}
//MARK: - Data Source Delegate Methods
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "goToItems", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as! ToDoListViewController
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.selectedCategory = categoryArray[indexPath.row]
}
}
//MARK: - Add New Categories
@IBAction func addNewCategory(_ sender: UIBarButtonItem) {
var textField = UITextField()
let alert = UIAlertController(title: "Add New Check-o Category", message: "", preferredStyle: .alert)
let addNewCategory = UIAlertAction(title: "Add New Category", style: .default) { (addNewCategory) in
let newItem = Category(context: self.context)
newItem.categoryName = textField.text!
self.categoryArray.append(newItem)
self.saveItems()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (cancelAction) in
self.dismiss(animated: true, completion: nil)
self.tableView.reloadData()
}
alert.addTextField { (alertTextField) in
alertTextField.placeholder = "Start Typing Your New Category"
textField = alertTextField
}
alert.addAction(addNewCategory)
alert.addAction(cancelAction)
present(alert, animated: true, completion: nil)
}
//MARK: - TableView Manipulation Methods
func saveItems () {
do {
try context.save()
} catch {
print ("Error saving context \(error)")
}
tableView.reloadData() //This method reloads data so the new item from the text field alert is added to the To Do Item Array
}
func loadItems (with request : NSFetchRequest<Category> = Category.fetchRequest()) {
do {
categoryArray = try context.fetch(request)
} catch {
print ("Error Fetching Data From Context \(error)")
}
tableView.reloadData()
}
}
Хотите иметь возможность отфильтровывать любое слово, введенное в строке поиска, из контроллера элемента do и фактически отображать результат запроса.