I have really nasty errors while working with something apparently simple.
I have an NSArray
which I fill with words the first time the app launches.
Then at a certain point I want to use the array, so I declared another array inside the class:
var localArray = NSUserDefaults.standardUserDefaults().arrayForKey("array")!
Then I want to display a word in a label. And when a user presses a button (forward/backward) the next/previous word appears. Pretty simple, right? It is, but somehow I get really nasty errors.
I have 2 methods for the next/previous words:
@IBAction func nextWord(sender: AnyObject) {
if let currentIndex = localArray.indexOf(label.text!)
{
if currentIndex == localArray.count-1
{
label.text = localArray[0] as? String
}
else
{
label.text = localArray[currentIndex+1]
}
}
}
The other method for going backwards is identical (with necessary modifications).
And in viewDidLoad
I just set the label's text:
label.text = localArray[0] as? String
The problem is with the if let
statements. Before using the user defaults, I just initialized localArray
with a few strings. And everything worked fine. But once I added the user defaults, madness began. I had errors everywhere I used localArray
saying that the array isn't unwrapped. So I added !
after the user defaults array when initializing the local one.
But the last 2 errors (in the if let
statements) make no sense. Now the indexOf()
method throws an error, a thing that didn't happen before. And it also tells me that it can't convert the string (label.text!) to @noescape (AnyObject) throws -> Bool
.
So now I need to transform that string to an NSString
for that to work or what? I found something about "bridging" related to arrays in user defaults. Is that my issue?
Now here's what bugs me: WHY do I have to explicitly downcast a string in the array to a string? WHY did the indexOf
method change.
Doesn't an unwrapped optional act like a non-optional?
The object you are creating is not an array (at least the compiler doesn't know it is). The function arrayForKey("array")!
is returning an AnyObject
, not an Array
. So from there on out the compiler thinks this object is an AnyObject
. How I would solve this (may not be the correct way) would be to cast the Array immediately:
if let myArray: AnyObject! = NSUserDefaults.standardUserDefaults().objectForKey("array") {
//Your array exists, cast it now and use it
var localArray = myArray as! Array<String>
}
else
{
//Something bad happened, the array isn't there.
}
Then you will have to do unwrapping later on. If you know this object will always exist and the cast will always work you can change the ?
to !
.
Look to this answer for a little more information.