argument for generic parameter could not be inferred

l-spark picture l-spark · May 21, 2015 · Viewed 39.6k times · Source

I'm trying to save an array with NSUserDefaults and then load the array, but I get the error "argument for generic parameter could not be inferred." Is there anything I am doing wrong? No one seems to be having this problem in swift, so I can't find any solutions.

IBAction func loadData(sender: AnyObject) {
    if let testCompositeArray = defaults.objectForKey("testScoreSATArray") as? Array {        
        self.showDataLabel.text = defaults.objectForKey("testScoreSATArray") as Array
    }
}

Answer

Airspeed Velocity picture Airspeed Velocity · May 21, 2015

The reason you received your original error is that in Swift, Array is a generic container that holds values of a specific type. So you can have an Array<Int> that holds integers, or an Array<String> that holds strings. But you can’t have just an Array. The type of the thing the array contains is the generic parameter, and Swift is complaining because it can’t figure out what that type should be. Sometimes it can infer that type from the context of the code around it, but not always, as in this case.

You can resolve the problem by giving the type of the thing you are storing:

IBAction func loadData(sender: AnyObject) {
    if let testCompositeArray = defaults.objectForKey("testScoreSATArray") as? Array<Int> {

            self.showDataLabel.text = toString(testCompositeArray)
    }
}

Instead of writing Array<Int>, you can write the shorter form, [Int]

You can also solve the problem by using NSArray, as you’ve found. Unlike Array, NSArray doesn’t use generics, since it originates in Objective-C which has a different approach to Swift. Instead, NSArray holds only one kind of thing, an AnyObject. This is is a reference that can point to instances of any class.

However, there’s a big downside to using NSArray and AnyObject, which is that every time you use a value they contain, you often have to “cast” the value to a real thing, like an integer or a string. This can be a pain, and worse, sometimes can cause errors when you assume you have one kind of thing when actually you have another. Swift generally encourages you to be more specific about types to avoid errors like this.