0

How do I prevent my text from displaying Optional() in the Swift interpolation?

My text displaying is :

---You can only switch properties once all images from Optional("PPP") have finished uploading.---

Here is my code

let imagesLeftToUpload = syncer!.imagesToUpload?.count
        if(imagesLeftToUpload != nil && imagesLeftToUpload! > 0) {
            let propertyConfig = syncer!.getPropertyConfig()
            var propertyNameStr: String = ""
            if(propertyConfig != nil && propertyConfig!.propertyName != nil) {
                propertyNameStr = "from \(propertyConfig!.propertyName)"
            }
            messageText.text = "You can only switch properties once all images\(String(describing: propertyNameStr)) have finished uploading."
        }
Kamilski81
  • 14,409
  • 33
  • 108
  • 161

3 Answers3

4

Use optional binding to safely unwrap the optionals, then use String interpolation on the non-optional value.

guard let imagesLeftToUpload = syncer?.imagesToUpload?.count, imagesLeftToUpload > 0 else {return}
guard let propertyConfig = syncer?.getPropertyConfig(), let propertyName = propertyConfig.propertyName else {return}
messageText.text = "You can only switch properties once all images\(propertyName) have finished uploading."
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • Is there a difference between guard and if statements? – Siyavash Sep 13 '17 at 23:18
  • 1
    Yes, a guard statement lets you use the safely unwrapped value in the same scope, not just inside the statement and it also enables you to exit the current scope early in case the condition fails. – Dávid Pásztor Sep 13 '17 at 23:19
  • 2
    Yes: https://stackoverflow.com/questions/32256834/swift-guard-vs-if-let – JAB Sep 13 '17 at 23:19
  • +1: guard let or if let is the cleanest way to deal with Optionals here. If you inverted these checks I think you could get away with a single guard. – charles-allen Sep 14 '17 at 00:12
1

Swift is doing this because you provided an optional string, not a string. To solve it you need to unwrap the optional.

You can either use ! to unwrap an optional string, such as:

messageText.text = "You can only switch properties once all images\(propertyNameStr!) have finished uploading."

Or you can use a if statement to unwrap the optional.

if let nameString = propertyNameStr {
    messageText.text = "You can only switch properties once all images\(nameString) have finished uploading."
}
Yuan Fu
  • 191
  • 2
  • 15
  • Using ! operator is not 100% save. It crashes your program when propertyNameStr is nil at the time it is unwrapped. – Yuan Fu Sep 13 '17 at 23:27
  • 1
    "you provided an optional, not a string" That is not precisely true. `propertyNameStr' has type 'String?', which is an optional String. There's no such thing as just an `Optional`, since `Optional` is actually a generic enum, whose value can either be `nil` or a non-nil value of the generic type. – Dávid Pásztor Sep 13 '17 at 23:30
0

I ended up going with the following because I didn't want to use guard, but I wanted to always display the message:

            var propertyNameStr = ""
            if let propertyName = syncer!.getPropertyConfig()?.propertyName {
                propertyNameStr = "from \(propertyName) "
            }
            messageText.text = "You can only switch properties once all images \(propertyNameStr)have finished uploading."
Kamilski81
  • 14,409
  • 33
  • 108
  • 161