I have a tableview that displays a list of objects of type String, using Core Data, where the user can keep adding new objects to that same table. There´s one limitation, though, which is not allow to add duplicates. I managed to avoid duplicates that are the same for example: "Bank"/"Bank". Problem is I also need to block duplicates like this: "Bank"/"bAnk" or "Bank"/"BAnk" and so on, but I have no idea of how to do this.
Here is my code:
func checkDuplicates(catName: String) -> Bool {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
var contents = [NSManagedObject]()
var items = [String]()
let fetchRequest = NSFetchRequest(entityName: "Categories")
do {
let results = try managedContext.executeFetchRequest(fetchRequest)
contents = results as! [Items]
for item in contents {
items.append(item.valueForKey("name") as! String)
}
} catch {
print("error")
}
if items.contains(catName) {
return true
}
return false
}
It returns a Bool so that when it returns a duplicate I display an Alert telling the user he can add a duplicate.
So anyone can help my with this?
There is no need to fetch all objects in order to check for existing Core Data objects. You can create a fetch request with a predicate which searches for objects with the given name:
let fetchRequest = NSFetchRequest(entityName: "Categories")
fetchRequest.predicate = NSPredicate(format: "name ==[c] %@", catName)
Here ==[c]
stands for case-insensitive comparison.
An in fact you don't have to fetch objects at all. You can
check for matching objects with countForFetchRequest()
:
var error : NSError? = nil
let count = managedContext.countForFetchRequest(fetchRequest, error: &error)
if count == NSNotFound {
print("error:", error!.localizedDescription)
return false
} else if count >= 1 {
return true
} else {
return false
}
This is much more effective because the fetch request is executed as a "SELECT COUNT ..." query on the SQLite level, without fetching the objects into memory.