I have the following code to search a tableView. The contains format works fine for string arguments however can't seem to find the correct format to work with date arguments.
@objc func invoiceSearch(sender:NSSearchField) {
// print ("\(#function): \(sender.stringValue)")
let searchString = sender.stringValue
var predicate:NSPredicate = NSPredicate()
if searchString.isEmpty {
invoices = self.backUpInvoices
}
else{ // search field contains data
if (invoiceSearchField.cell as? NSSearchFieldCell)?.placeholderString == "All" {
predicate = NSPredicate(format: "invoiceNumber contains %@ OR invoiceCustName contains %@ OR invoiceStatus contains %@ OR invoiceDateCreated >= %@",searchString,searchString,searchString,searchString)
}
else if (invoiceSearchField.cell as? NSSearchFieldCell)?.placeholderString == "invoice Number" {
predicate = NSPredicate(format: "invoiceNumber contains %@",searchString)
}
else if (invoiceSearchField.cell as? NSSearchFieldCell)?.placeholderString == "invoice Customer"{
predicate = NSPredicate(format: "invoiceCustName contains %@",searchString)
}
else if (invoiceSearchField.cell as? NSSearchFieldCell)?.placeholderString == "invoice Status"{
predicate = NSPredicate(format: "invoiceStatus contains %@",searchString)
}
else if (invoiceSearchField.cell as? NSSearchFieldCell)?.placeholderString == "Invoice Date"{
predicate = NSPredicate(format: "invoiceDateCreated >= %@", searchString as CVarArg)
}
invoices = (self.backUpInvoices as NSArray).filtered(using: predicate) as! [Invoice]
}
invoiceCount = "Found \(items.count ) Invoices"
invoiceStatusLabel.stringValue = invoiceCount
self.tableView.reloadData()
}
InvoiceDateCreated is defined by the following within a NSObject class:
@objc var invoiceDateCreated: Date? = Date()
The error I get when trying to search on date is 2022-09-26 09:14:36.638553-0500 CashToMe[9107:6838576] [General] -[NSTaggedPointerString objCType]: unrecognized selector sent to instance
I have read through the following documentation Apple Doc for NSPredicate
How can I fix this. Also, if there is a better/newer way to code this I am open to changing the code.
Thanks
I figured this out. I had to create a date from the search string to use in the predicate>>>
Here is the working code:
@objc func invoiceSearch(sender:NSSearchField) {
let searchString = sender.stringValue
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYYMMdd"
var dateTemplate: String = "20000101"
var dateSearch: String = ""
var dateEndSearch: String = ""
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
var predicate:NSPredicate = NSPredicate()
if searchString.isEmpty {
invoices = self.backUpInvoices
}
else{ // search field contains data
if searchString.isContainsLetters == false { // If false must be a date search (Numerics or -)
dateSearch = dateTemplate // Code to handle a begin and end date in
if searchString.count < 9 { // the format YYYYMMDD-YYYYMMDD initially end date is
dateSearch.removeFirst(searchString.count) // set to current date
dateSearch = searchString + dateSearch
searchBeginDate = dateFormatter.date(from: dateSearch)!
}
else {
if searchString.count > 9 {
dateSearch.removeFirst(searchString.count-9)
dateEndSearch = searchString
dateEndSearch.removeFirst(9)
dateSearch = dateEndSearch + dateSearch
searchEndDate = dateFormatter.date(from: dateSearch)!
}
}
}
if (invoiceSearchField.cell as? NSSearchFieldCell)?.placeholderString == "All" {
predicate = NSPredicate(format: "invoiceNumber contains %@ OR invoiceCustName contains %@ OR invoiceStatus contains %@ OR invoiceDateCreated >= %@ AND invoiceDateCreated < %@",searchString,searchString,searchString,searchBeginDate as NSDate, searchEndDate as NSDate)
}
else if (invoiceSearchField.cell as? NSSearchFieldCell)?.placeholderString == "invoice Number" {
predicate = NSPredicate(format: "invoiceNumber contains %@",searchString)
}
else if (invoiceSearchField.cell as? NSSearchFieldCell)?.placeholderString == "invoice Customer"{
predicate = NSPredicate(format: "invoiceCustName contains %@",searchString)
}
else if (invoiceSearchField.cell as? NSSearchFieldCell)?.placeholderString == "invoice Status"{
predicate = NSPredicate(format: "invoiceStatus contains %@",searchString)
}
else if (invoiceSearchField.cell as? NSSearchFieldCell)?.placeholderString == "Invoice Date"{
predicate = NSPredicate(format: "invoiceDateCreated >= %@ AND invoiceDateCreated < %@", searchBeginDate as NSDate, searchEndDate as NSDate)
}
invoices = (self.backUpInvoices as NSArray).filtered(using: predicate) as! [Invoice]
}