5

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.

2 Answers 2

15

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:@" | "];
Sign up to request clarification or add additional context in comments.

4 Comments

+1 for map and join, it's probably the easiest solution to this problem and likely also the clearest.
Thanks @Brian. One small thing. When I get the final string, it looks like this Action1 | Action2 | Action3 |. It has an extra pipe at the end. How can I have the string without the trailing pipe like this Action1 | Action2 | Action3
@Isuru I've updated with a longer explanation on how to do exactly what you are attempting. I really think you want to avoid looping though as map/join is simpler.
@BrianNickel Thank you. It works great. I'm not familiar with the map function but I'm currently looking into it right now. Will reimplement it once I get the hang of it. Thanks again for the detailed answer.
5

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) |"
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.