Reputation: 255
var defaults = NSUserDefaults.standardUserDefaults();
var titlesForTip : [NSString]? = defaults.objectForKey("titleForTipSegment") as? [NSString]
if titlesForTip == nil //Check for first run of app
{
titlesForTip = ["18%", "20%", "22%"]; //Default value
}
// it is ok to get first and last elements
println( titlesForTip?.first)
for item in titlesForTip {//**error [NSString]? does not have a member named Generator**
println(item)
}
//**error type [NSString]? does not conform to protocol sequence type**
for (var index, var value) in enumerate(titlesForTip) {
println("Item \(index + 1): \(value)")
}
titlesForTip[1];//**error [NSString]? does not have a member named subscript**
in Debug window it shows titlesForTip including 3 elements and show in titlesForTip[0]... titlesForTip[2], but I can not visit it with [].
it is running in Xcode 6.1.1, I do not know how to iterate with it.
An error on my code: var titlesForTip : [NSString]? = defaults.objectForKey("titleForTipSegment") as? [NSString] if (titlesForTip? == nil || titlesForTip! == []) //Check for first run of app { titlesForTip = ["18%", "20%", "22%"] //Default value } objectForKey will return null array when there are nothing, so titlesForTip ==nil will never occur.
Upvotes: 1
Views: 971
Reputation: 535305
As you've been told, it's merely because your array is wrapped in Optional - because you wrapped it in an Optional by using the as?
operator. That's okay to do, and is a wise idea because it's safe. But then you must unwrap it:
var titlesForTip : [NSString]? // "wrap me in an Optional"
titlesForTip = ["18%", "20%", "22%"]
for item in titlesForTip! { // "unwrap me"
println(item)
}
In your actual code, what I would do is use a conditional binding to unwrap:
var titlesForTip : [NSString]? =
defaults.objectForKey("titleForTipSegment") as? [NSString]
if let titlesForTip = titlesForTip { "unwrap me safely"
// ...here, titlesForTip is unwrapped and safe to use...
}
However, in actual fact there is no need for any of that code, because there is no need to check for nil and supply a default value. Instead, call registerDefaults:
- that's what it's for. That way, objectForKey("titleForTipSegment")
will always have an [NSString]
value and you can just cast unconditionally.
Upvotes: 0
Reputation: 13333
You've created titlesForTip
as an optional that may contain an array of NSStrings
. Therefore, you need to check if it contains anything by unwrapping it before you can access its elements, or iterate on it.
Use code similar to this:
var defaults = NSUserDefaults.standardUserDefaults()
var titlesForTip : [NSString]? = defaults.objectForKey("titleForTipSegment") as? [NSString]
if titlesForTip == nil //Check for first run of app
{
titlesForTip = ["18%", "20%", "22%"] //Default value
}
if let unwrappedTitlesForTip = titlesForTip {
// it is ok to get first and last elements
println( unwrappedTitlesForTip.first)
for item in unwrappedTitlesForTip {
println(item)
}
for (var index, var value) in enumerate(unwrappedTitlesForTip) {
println("Item \(index + 1): \(value)")
}
unwrappedTitlesForTip[1] // need to do something with this, won't work just on a line on its own
}
Alternatively, you could set it so you don't use an optional, by setting the default value first, and overriding it if you get something from the NSDefaults, like this:
var defaults = NSUserDefaults.standardUserDefaults()
var titlesForTip : [NSString] = ["18%", "20%", "22%"]
if let storedValue = defaults.objectForKey("titleForTipSegment") as? [NSString] {
titlesForTip = storedValue
}
// it is ok to get first and last elements
println( titlesForTip.first)
for item in titlesForTip {
println(item)
}
for (var index, var value) in enumerate(titlesForTip) {
println("Item \(index + 1): \(value)")
}
titlesForTip[1] // need to do something with this, won't work just on a line on its own
Upvotes: 1