Isuru
Isuru

Reputation: 31283

Appending text in a loop in Swift

I need to append an array of string and finally get a single string to be displayed in a UILabel in the following format.

Action1 | Action2 | Action3 | Action4

for action in actions {

    actionLabel.text += "\(action.name) |"
}

This gives me the following error.

'String?' is not identical to 'UInt8'.

Any reason for this error? Is there any other way to accomplish this?

Thank you.

Upvotes: 5

Views: 8746

Answers (2)

Brian Nickel
Brian Nickel

Reputation: 27550

This is one of Swift's many cryptic error messages. As far as I can tell because the left side and right side don't match (Optional<String> vs String), its best guess is that you meant for both sides to be UInt8.

To get over the fact that UILabel.text is optional, you can do things the long way:

actionLabel.text = (actionLabel.text ?? "") + "\(action.name) |"

This gets the current value or a blank string and appends the text. You could also avoid the problem functionally:

actionLabel.text = join(" | ", map(actions, { $0.name }))

Update

With regards to iterative solution having an extra | at the end in the "", I was trying to illustrate the solution to just the line causing the error. Your posted code also makes assumptions about actionLabel having been initially blank and has some (likely insignificant) performance costs of setting label text multiple times.

A complete iterative approach could look something like this:

var text = ""
for action in actions {
    if text.isEmpty {
        text = action.name
    } else {
        text += " | \(action.name)"
    }
}
actionLabel.text = text

Mapping and joining are such common operations that most languages have clean succinct ways of doing it without iteration. For example, I would recommend the following in Objective-C:

actionLabel.text = [[actions valueForKeyPath:@"name"] componentsJoinedByString:@" | "];

Upvotes: 15

Kirsteins
Kirsteins

Reputation: 27335

text property is optional can be nil. You can use optional chaining to over come this. Also set initial text before going through the loop.

if actionLabel.text == nil {
    actionLabel.text = ""
}

for action in actions {
    actionLabel.text? += "\(action.name) |"
}

Upvotes: 5

Related Questions