0

I'm trying to call retrieveData() when a user presses a button.

extension ViewController {

    func doOAuthFitbit2() {

        let oauthswift = OAuth2Swift(
            consumerKey:    "*****",
            consumerSecret: "*****",
            authorizeUrl:   "https://www.fitbit.com/oauth2/authorize",
            accessTokenUrl: "https://api.fitbit.com/oauth2/token",
            responseType:   "code"
        )

        oauthswift.accessTokenBasicAuthentification = true
        oauthswift.authorizeURLHandler = getURLHandler()
        let state = generateState(withLength: 20)

        let _ = oauthswift.authorize(
            withCallbackURL: URL(string: "smart://oauth-callback")!,
            scope: "profile nutrition",
            state: state,
            success: { credential, response, parameters in
                self.retrieveData(oauthswift)
        },
            failure: { error in
                print(error.description)
        }
        )
    }

    func retrieveData(_ oauthswift: OAuth2Swift) {
        print("retrieveData")
        let _ = oauthswift.client.get(
            "https://api.fitbit.com/1/user/-/profile.json",
            parameters: [:],
            success: { response in
                let jsonDict = try? response.jsonObject()
                print(jsonDict as Any)
        },
            failure: { error in
                print(error.description)
        }
        )
    }
}

I have the following in ViewController.swift

@IBAction func btnRetrieveData(_ sender: Any) {
    retrieveData(oauthswift)
}

I get the following error:

Cannot convert value of type 'OAuthSwift?' to expected argument type 'OAuth2Swift'

Which I assume is because "oauthswift" is declared inside the doOAuthFitbit2() function.

Do I need to refactor the code so the retrieveData() function is nested inside the doOAuthFitbit2() function? how would I call that in ViewController.swift?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Dachan
  • 157
  • 4
  • 16

1 Answers1

0

Your oauthswift property is local to the doOAuthFitbit2() function, and thus you cannot access it from the button method (or any other method). I'd suggest to start with, you could add it as a global property that doOAuthFitbit2() updates, e.g.:

var oauthswift: OAuth2Swift!
// ^ declare global variable

func doOAuthFitbit2() {

    oauthswift = OAuth2Swift(
    // ^ reference the global variable and set it up here
        consumerKey:    "*****",
        consumerSecret: "*****",
        authorizeUrl:   "https://www.fitbit.com/oauth2/authorize",
        accessTokenUrl: "https://api.fitbit.com/oauth2/token",
        responseType:   "code"
    )

    oauthswift.accessTokenBasicAuthentification = true
    oauthswift.authorizeURLHandler = getURLHandler()
    let state = generateState(withLength: 20)

    let _ = oauthswift.authorize(
        withCallbackURL: URL(string: "smart://oauth-callback")!,
        scope: "profile nutrition",
        state: state,
        success: { credential, response, parameters in
            self.retrieveData(oauthswift)
    },
        failure: { error in
            print(error.description)
    }
    )
}

You can then do:

func retrieveData() {
//                ^ you don't need to pass an arg here, since it's globally accessible
    print("retrieveData")
    let _ = oauthswift.client.get(
        "https://api.fitbit.com/1/user/-/profile.json",
        parameters: [:],
        success: { response in
            let jsonDict = try? response.jsonObject()
            print(jsonDict as Any)
    },
        failure: { error in
            print(error.description)
    }
    )
}

That said, there are more stable ways of implementing this - like a shared instance (singleton) that can be accessed globally throughout the application, shared delegates/protocols, or the iOS keychain APIs. I won't get into those though - you'd need to do some learning and reading there.

brandonscript
  • 68,675
  • 32
  • 163
  • 220