Swift UISearchBar通过数组进行的查询不起作用:(

Swift UISearchBar通过数组进行的查询不起作用:(,swift,xcode,core-data,predicate,nsfetchrequest,Swift,Xcode,Core Data,Predicate,Nsfetchrequest,我正在尝试使用核心数据构建一个待办事项列表,以持久化来自类别视图控制器项数组和相应类别项数组的数据。我在实体之间建立了一种关系,因此当从根控制器选择一个类别时,将执行一个到相应项目列表的序列。一切正常来自items controller的筛选器未按预期工作,当在搜索栏中键入所需的项目以进行搜索时,它只返回第一个项目,无论要筛选哪个词。我不知道问题可能在哪里,如果有人能帮我一把,我将非常感谢 我已经尝试过以我所知的任何方式修改委托方法,所以我的想法太多了 **ToDoListVC 导入UIKit

我正在尝试使用核心数据构建一个待办事项列表,以持久化来自类别视图控制器项数组和相应类别项数组的数据。我在实体之间建立了一种关系,因此当从根控制器选择一个类别时,将执行一个到相应项目列表的序列。一切正常来自items controller的筛选器未按预期工作,当在搜索栏中键入所需的项目以进行搜索时,它只返回第一个项目,无论要筛选哪个词。我不知道问题可能在哪里,如果有人能帮我一把,我将非常感谢

我已经尝试过以我所知的任何方式修改委托方法,所以我的想法太多了

**ToDoListVC

导入UIKit 导入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()
    }
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()
}
}

**类别视图控制器

导入UIKit 导入CoreData

类类别ViewController: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()
    }
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()
}
var categoryArray=[Category]()
让上下文=(UIApplication.shared.delegate为!AppDelegate)。persistentContainer.viewContext
重写func viewDidLoad(){
super.viewDidLoad()
打印(FileManager.default.url(用于:.documentDirectory,位于:.userDomainMask中))
loadItems()
tableView.register(UINib(nibName:“CustomToDoItemCell”,bundle:nil),强制重用标识符:“CustomToDoItemCell”)
}
//MARK:-TableView数据源方法
重写func tableView(tableView:UITableView,numberofrowsinssection:Int)->Int{
返回categoryArray.count
}
重写func tableView(tableView:UITableView,cellForRowAt indexath:indexPath)->UITableViewCell{
让cell=tableView.dequeueReusableCell(标识符为:“CustomToDoItemCell”,for:indexPath)作为!CustomToDoItemCell
让item=categoryArray[indexPath.row]
cell.toDoBodyText?.text=item.categoryName
cell.toDoBodyText=UILabel(帧:CGRect(x:16,y:11,宽度:160,高度:21))
返回单元
}
//标记:-数据源委托方法
重写func tableView(tableView:UITableView,didSelectRowAt indexPath:indexPath){
性能检查(带有标识符:“goToItems”,发送者:self)
}
覆盖功能准备(对于segue:UIStoryboardSegue,发送方:有吗?){
让destinationVC=segue.destination为!ToDoListViewController
如果让indexPath=tableView.indexPathForSelectedRow{
destinationVC.selectedCategory=categoryArray[indexPath.row]
}
}
//标记:-添加新类别
@iAction func addNewCategory(uu发件人:UIBarButtonim){
var textField=UITextField()
let alert=UIAlertController(标题:“添加新的检查-o类别”,消息:,首选样式:。警报)
让addNewCategory=UIAlertAction(标题:“添加新类别”,样式:。默认值){(addNewCategory)在
让newItem=Category(上下文:self.context)
newItem.categoryName=textField.text!
self.categoryArray.append(newItem)
self.saveItems()
}
让cancelAction=UIAlertAction(标题:“Cancel”,样式:.Cancel){(cancelAction)在
self.disclose(动画:true,完成:nil)
self.tableView.reloadData()
}
alert.addTextField{(alertTextField)位于
alertTextField.placeholder=“开始键入新类别”
textField=alertTextField
}
alert.addAction(addNewCategory)
alert.addAction(取消操作)
当前(警报、动画:真、完成:无)
}
//MARK:-表视图操作方法
func saveItems(){
做{
尝试context.save()
}抓住{
打印(“保存上下文时出错\(错误)”)
}
tableView.reloadData()//此方法重新加载数据,以便将文本字段警报中的新项添加到待办事项数组中
}
func loadItems(请求为:NSFetchRequest=Category.fetchRequest()){
做{
categoryArray=try context.fetch(请求)
}抓住{
打印(“从上下文提取数据时出错\(错误)”)
}
tableView.reloadData()
}
}

希望能够从“待办事项”控制器中筛选搜索栏中键入的任何单词,并实际显示查询结果。

有关类似问题和答案,请参阅。有关类似问题和答案,请参阅