Honey Honey - 10 months ago 50
Swift Question

Why do I get error when I do optional chaining?

protocol textingprotocol : class {
func didEnterText (text:String)

class secondViewController: UIViewController {
weak var delegate:textingprotocol?

@IBOutlet weak var txtField: UITextField?

@IBAction func dismissButton(sender: UIButton) {

delegate!.didEnterText(txtField?.text) // A: doesn't work
delegate!.didEnterText(txtField?.text!) // B: doesn't work
delegate!.didEnterText((txtField?.text)!) // C: works


A: Am I not already doing optional chaining and the line would only work if text has a value if not then it would gracefully fail?
Yet it gives:

Value of optional type 'String?' not unwrapped; did you mean to use
'!' or '?'?

B: Even when I am given compiler error of above, well I do unwrap it, still it's not satisfied it wants it to be like C. To my understanding with the
I have unwrapped txtField and with the
I have unwrapped text, still confused why it doesn't work

Why does C work but not B? Isn't there a more cleaner way than line C? Line C looks very unappealing.

Answer Source

didEnterText does not take a String?. It takes a String. Thus, you cannot use simple optional chaining with question marks to get its argument. You must actually unwrap to a String, not tentatively unwrap to a String?-or-nil.

Now, txtField is an Optional, so you need to unwrap it.

And a UITextField's text property is an Optional, so you need to unwrap it too.

So the simplest approach is to unwrap them both, absolutely:


If you don't want to do that (because you fear that one of them will be nil and crash your app), you will have to protect the whole thing with if let:

    if let s = txtField?.text {