Search code examples
arraysswiftcore-dataduplicatesnsfetchrequest

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?


Solution

  • 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.