Search code examples
iosswiftnsarraynsuserdefaults

Evaluate if item is already in Array


I'm trying to evaluate if an item is already in existingArr so that I don't add it multiple times.

But I keep getting an error "Cannot convert value of type String to expected argument type @noescape (AnyObject) throws -> Bool" when I try to evaluate if the existingArr already contains an item, on this line if existingArr.contains(nD.dayOfTheWeek) == false in:

for days in results! {
    let nD = DayClass()
    nD.dayOfTheWeek = days[“D”] as! String
        //check if there is already an existing Day array in prefs
        if var existingArr = NSUserDefaults.standardUserDefaults().arrayForKey("D") {
            //if so append the new value to that array and store it
            if existingArr.contains(nD.dayOfTheWeek) == false {
                let defaults = NSUserDefaults.standardUserDefaults()
                defaults.setObject(existingArr, forKey: "D")
                defaults.synchronize()
            }
        } else {
            //create a new array and store it
            let defaults = NSUserDefaults.standardUserDefaults()
            defaults.setObject([nD.dayOfTheWeek], forKey: "D")
            defaults.synchronize()
        }
    }

I have a general idea of what it is trying to tell me, but not enough to actually figure it out. Any help is very appreciated.


Solution

  • The main issue here is that arrayForKey: returns [AnyObject]?, and not all objects are Equatable.

    Why is Equatable necessary? There are two implementations for contains: one that takes an object, and one that takes a predicate (in the form of a closure). However, the contains that takes an object requires the generator (the array in this case) to have elements (the objects in the array) to conform to Equatable.

    Because not all objects are Equatable, and existingArr is of type [AnyObject]?, Xcode assumes you are trying to call the predicate form of contains. However, nD.dayOfTheWeek is not a closure, so Xcode throws an error saying that it isn't a closure.

    To fix this, you need to cast the existingArr to type [String], because that's what type it is and strings are Equatable:

    if var existingArr = NSUserDefaults.standardUserDefaults().arrayForKey("D") as? [String] {
    

    Note: This shouldn't actually work because String is actually a structure (not an object), but for some reason it still works in a simple playground test. If someone could explain why in the comments, that would be great.