Marco Almeida Marco Almeida - 1 year ago 249
Swift Question

How to avoid duplicate entries in Array with case sensitive and case insensitive mixed Strings in Swift?

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?

Answer

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.