john vuong
john vuong

Reputation: 255

How to iterate NSString in Swift?

    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

Answers (2)

matt
matt

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

Dave Wood
Dave Wood

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

Related Questions