How to convert Optional String to String

28,070

Solution 1

Optional string means that the string may be nil. From "The Basics" in the Swift Programming Language

Swift also introduces optional types, which handle the absence of a value.

When you print an optional string on console it will tell you that it is an optional. So the value of the string dos not contain the "Optional" keyword...

For example

var str : String?
str = "Hello" // This will print "Optional("Hello")"
print(str)
print(str!) // This will print("Hello") 

But str value is "Hello" . It is an optional string

Solution 2

The problem is not here

Your property is declared as an implicitly unwrapped optional String.

var topicName: String!

So when you use it the value is automatically unwrapped.

Example:

var topicName:String!
topicName = "Life is good"
print(topicName)

Output

Life is good

As you can see there is no Optional(Life is good) in the output. So this code is correct.

My theory

My guess is that you are populating topicName with a String that already contains the Optional(...) word.

This is the reason why you are getting the Optional(...) in the output.

Testing my theory

To test this scenario let's add an observer to your property

willSet(newValue) {
    print("topicaName will be set with this: \(newValue)")
}

I expect you will see something like this in the log

topicaName will be set with this: Optional(Hello)

Finding the real problem (aka who is writing the String 'Optional("Hello")'?)

If this does happen just put a breakpoint in the observer and find the instruction in your project that is writing the String Optional("Hello") in your property.

Share:
28,070
Hanslen Chen
Author by

Hanslen Chen

Updated on July 09, 2022

Comments

  • Hanslen Chen
    Hanslen Chen almost 2 years
    @IBOutlet var navBar: UINavigationBar!
    @IBOutlet var menuButton: UIBarButtonItem!
    @IBOutlet var topicNameLabel: UILabel!
    var topicName:String!
    override func viewDidLoad() {
        super.viewDidLoad()
    
        // Do any additional setup after loading the view.
        menuButton.target = self.revealViewController()
        menuButton.action = Selector("revealToggle:")
    
        navBar.barTintColor = UIColor(red: 0, green: 0.4176, blue: 0.4608, alpha: 1)
        topicNameLabel.text = self.topicName
    
    }
    

    That's my code, I will pass a string to the topicName by prepareForSegue, however, I find that in the simulator, my topicNameLabel shows "Optional(The text I want)". I just want the "The text I want", but do not need the Optional. Could any one help me?

  • Hanslen Chen
    Hanslen Chen about 8 years
    I try to edit that to "topicNameLabel.text = self.topicName!" However, that still not works. :-(
  • Luca Angeletti
    Luca Angeletti about 8 years
    The OP defined topicName ad an implicitly unwrapped String, this is the declaration var topicName:String! and he is using it simply writing topicName. It's the same result of declaring it as String? and then performing a force unwrap as you are doing.
  • Hanslen Chen
    Hanslen Chen about 8 years
    I tried, however, there is some thing strange, print("StackOverflow told me this (topicName)") However, it prints StackOverflow told me this Optional("Optional(My baby don\'t eat food)")
  • Luca Angeletti
    Luca Angeletti about 8 years
    @HanslenChen: Did you create the property observer?
  • Hanslen Chen
    Hanslen Chen about 8 years
    I find my problem 0.0 But I still have some questions to ask that let topic:String = "Recruiting a private doctor" self.performSegueWithIdentifier("topicDetailSegue", sender: topic) I use these to pass the topic string to my destination viewController, actually the topic is the topicName, and the type is string!, why it will come with an Optional?
  • Luca Angeletti
    Luca Angeletti about 8 years
    @HanslenChen: then why are you printing topicName? In my instructions I used this code willSet(newValue) { print("topicaName will be set with this: \(newValue)") }. Please follow my instruction and tell me the result.
  • Hanslen Chen
    Hanslen Chen about 8 years
    Also in the prepareForSegue I have, [ var topic:String topic = String(sender) topicVC.topicName = topic as String!]
  • Luca Angeletti
    Luca Angeletti about 8 years
    @HanslenChen: That can be the problem. What is the type of sender?
  • Hanslen Chen
    Hanslen Chen about 8 years
    sender is anyObject. Now, I fix that by doing "subStringFromIndex". The problem is just as you said that the string really contains "Optional()". However, I was still confused why it will contain that, actually, I think I have done something like "topic as String!". It should not be optional?
  • Luca Angeletti
    Luca Angeletti about 8 years
    @HanslenChen: We are almost there. But I need to know the actual type of sender (AnyObject is just the protocol) in order to properly cast it. Please add to prepareForSegue the following code print("sender.dynamicType: \(sender.dynamicType)"), run your project and then tell me what you find into the log.
  • Hanslen Chen
    Hanslen Chen about 8 years
    the output is sender.dynamicType: Optional<AnyObject>.