Gimme the 411
Gimme the 411

Reputation: 1044

Binary operator '+' cannot be applied to operands of type 'String' and '() -> String'

class ViewController: UIViewController{
    var token: String?

    func settoken(newtoken: String){
        token = newtoken
    }

    func gettoken() -> String{
        return token!
    }

    func gotoverifyphone(){
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let verifyphone = storyboard.instantiateViewController(withIdentifier: "verifyphone")
        OperationQueue.main.addOperation{
            self.present(verifyphone, animated: true, completion: nil)
        }
    }

    @IBAction func btnPressed(_ sender: Any){
        ...some code
        let newtoken = json["message"] as? String
        self.settoken(newtoken: newtoken!)
        self.gotoverifyphone()
    }
}

ViewController.swift

class VC_VerifyPhone: UIViewController {
    @IBAction func btnVerifyPressed(_ sender: Any){
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        let token = "Bearer " + ViewController.gettoken(ViewController)
// the line above shows Binary operator '+' cannot be applied to operands of type 'String' and '() -> String'
        request.addValue("authorization", forHTTPHeaderField: token)
    }
}

VC_VerifyPhone.swift

On the 2nd last line of the 2nd class, it shows the error:

Binary operator '+' cannot be applied to operands of type 'String' and '() -> String'

What am I doing wrong and how can I fix it?

EDIT:

Now I'm getting this error:

Instance member 'gettoken' cannot be used on type 'ViewController'; did you mean to use a value of this type instead?

Upvotes: 0

Views: 927

Answers (3)

OOPer
OOPer

Reputation: 47906

You need to access the very instance of ViewController. which invoked the VC_VerifyPhone.

You may need to pass self when opening the VC_VerifyPhone or some closure returning the same value as gettoken() or there may be some other ways. But anyway you need to pass some info from ViewController to VC_VerifyPhone.

Why don't you pass the token directly?

In your UIViewController:

func gotoverifyphone(){
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let verifyphone = storyboard.instantiateViewController(withIdentifier: "verifyphone") as! VC_VerifyPhone
    verifyphone.passedToken = token //<- pass your token directly
    OperationQueue.main.addOperation{
        self.present(verifyphone, animated: true, completion: nil)
    }
}

In VC_VerifyPhone:

var passedToken: String?

@IBAction func btnVerifyPressed(_ sender: Any){
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    if let passedToken = passedToken { //Use the passed token here
        let token = "Bearer " + passedToken
        request.addValue("authorization", forHTTPHeaderField: token)
    } else {
        //This may never happen, but you may need some output while debugging.
        print("VC_VerifyPhone opened without setting `passedToken`")
    }
}

Upvotes: 1

Nick Kohrn
Nick Kohrn

Reputation: 6049

The way that your code is structured requires you to have an instance of ViewController, which has its token property set. Once you have that, then you can substitute viewController.getToken() for ViewController.gettoken(ViewController).

You first need a view controller with a token. For example:

let controller = ViewController()
controller.settoken(newtoken: "abc123")

Then, you can call controller.getToken() and interpolate that into your string, which looks like this:

let token = "Bearer " + controller.getToken()

Upvotes: 0

CRD
CRD

Reputation: 53010

You've been bitten by a bit of Swift fun/weirdness/etc. depending on your point of view!

gettoken() is an instance method of the ViewController class and should be called on an instance. E.g something like:

var myViewController : ViewController = ...
...
let token = myViewController.gettoken()

You have not done this, instead you've called it on the class itself which isn't the same thing at all. You need an instance of your ViewController class on which to call get token().

Why the confusing error?

For reasons I won't attempt to explain Swift 4 (at least, Swift is a moving target) allows you to write:

myViewController.gettoken()

as

ViewController.gettoken(myViewController)()

And this is partly what you wrote and the error messages refers to this form. (For the terminally curious think of instance methods having a type of the form class -> arguments -> result and being members of the class.)

Upvotes: 3

Related Questions