在Swift中以编程方式在视图之间传递OAuth令牌

时间:2014-11-19 22:47:56

标签: swift

我一直试图将变量从一个视图传递到另一个视图。我故意在没有故事板的情况下以编程方式执行此操作。

ViewController created有一个UIButton,按下时调用AuthoriseController。

然后,AuthoriseController加载一个UIWebView,在特定的URL上打开它,例如https://foursquare.com/oauth2/authenticate?client_id=xxxxx&response_type=token&redirect_uri=yyyyy

这会加载OAuth屏幕。用户登录后,控制权返回给AuthoriseController,我在其中提取重定向URI中返回的access_token。

exctraction工作得很好,我可以抓住令牌,我的问题是我想把令牌送回我的ViewController,这样当用户再次按下按钮时,它将可用于HTTP请求(在我刚刚打印令牌的那一刻。)

我的ViewController和AuthoriseController实现了一个名为DataProtocol的协议,我希望可以在协议之间共享令牌。

的ViewController:

import UIKit

class ViewController: UIViewController {

var delegate: DataProtocol? = nil

func setUpView(){
    let firstView = UIView()
    let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
    firstView.setTranslatesAutoresizingMaskIntoConstraints(false)
    firstView.backgroundColor = UIColor(red: 0.75, green: 0.75, blue: 0.1, alpha: 1.0)
    view.addSubview(firstView)
    setUpButton(button)
    firstView.addSubview(button)
    setUpConstraints(firstView, button)
}

func setUpConstraints(firstView: UIView, _ button: UIButton) {
    let viewsDictionary = ["firstView":firstView,"button":button]
    let metricsDictionary = ["firstViewHeight":1334.0,"viewWidth":750.0 ]
    let firstViewHeightConstraintH:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:[firstView(viewWidth)]", options: NSLayoutFormatOptions(0), metrics: metricsDictionary, views: viewsDictionary)
    let firstViewHeightConstraintV:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:[firstView(firstViewHeight)]", options: NSLayoutFormatOptions(0), metrics: metricsDictionary, views: viewsDictionary)

    firstView.addConstraints(firstViewHeightConstraintH)
    firstView.addConstraints(firstViewHeightConstraintV)

    let buttonConstraintH:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-150-[button(>=80)]", options: NSLayoutFormatOptions.AlignAllCenterY, metrics: nil, views: viewsDictionary)
    let buttonConstraintV:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-300-[button]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)

    firstView.addConstraints(buttonConstraintH)
    firstView.addConstraints(buttonConstraintV)
}

func setUpButton(button: UIButton) {
    button.setTranslatesAutoresizingMaskIntoConstraints(false)
    button.setTitle("Authorise", forState: UIControlState.Normal)
    button.addTarget(self, action: "buttonPressed", forControlEvents: UIControlEvents.TouchUpInside)
    button.backgroundColor = UIColor.blueColor()
    button.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
}

override func shouldAutorotate() -> Bool {
    return false
}

func buttonPressed(){
    let ac = AuthoriseController()
    self.presentViewController(ac, animated: true, completion: nil)
    println("token in ViewController.buttonPressed: [\(self.delegate?.token)]")
}

override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = UIColor(red: 0.9, green: 0.9, blue: 1, alpha: 1.0)
    setUpView()
}
override func supportedInterfaceOrientations() -> Int {
    return Int(UIInterfaceOrientationMask.All.toRaw())
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}   
}

AuthoriseController:

import UIKit
import WebKit

class AuthoriseController: UIViewController, UIWebViewDelegate, DataProtocol {

var token: String = ""

let AUTH_URL = "https://foursquare.com/oauth2/authenticate?client_id=";
let RESP_TYPE_AND_KEY_AND_TOKEN = "&response_type=token&redirect_uri=";
let REDIRECT_URI : String = "ZZZZZZZZ";
let CLIENT_ID : String = "XXXXXXX";

var webview: UIWebView = UIWebView()

override func viewDidLoad() {
    super.viewDidLoad()
    var myViewController = ViewController()

    self.webview.frame = self.view.bounds
    self.webview.delegate = self
    self.view.addSubview(self.webview)

    var url: NSURL = NSURL.URLWithString(AUTH_URL + CLIENT_ID + RESP_TYPE_AND_KEY_AND_TOKEN + REDIRECT_URI)
    var urlRequest: NSURLRequest = NSURLRequest(URL: url)
    self.webview.loadRequest(urlRequest)
}

func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {
    token = getToken(request.URL.absoluteString!)
    println("token in AuthoriseController.webView: [\(token)]")
    if(!token.isEmpty) {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
    return true
}

func getToken(url: String) -> String {
    var token = ""
    if url.rangeOfString("#access_token") != nil{
        token = url.componentsSeparatedByString("=").last!
    }
    return token
}
}

以下是DataProtocol:

import Foundation

protocol DataProtocol {
    var token : String { get set }
}

当我这样做时:

  1. 启动应用程序
  2. 按“授权”按钮
  3. 成功登录(控制返回ViewController
  4. 再次按下按钮
  5. 输出:我得到了这个输出:

    token in ViewController.buttonPressed: [nil]
    token in AuthoriseController.webView: []
    token in AuthoriseController.webView: []
    token in AuthoriseController.webView: []
    token in AuthoriseController.webView: [VSKRNHJRS3NWPN3EEIYMCSZYJ2YMNSH4GBXNQFL1EMYLJ5TO]
    token in ViewController.buttonPressed: [nil]
    token in AuthoriseController.webView: []
    token in AuthoriseController.webView: [VSKRNHJRS3NWPN3EEIYMCSZYJ2YMNSH4GBXNQFL1EMYLJ5TO]
    

    我希望在第二次出现的ViewController.buttonPressed中看到令牌,而不是NIL。

    谁能看到我哪里出错了?任何帮助是极大的赞赏!史蒂夫

1 个答案:

答案 0 :(得分:0)

看起来委托已正确连接,但您没有将令牌发送给它。在AuthoriseController中,您需要为委托设置令牌:

func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {
    token = getToken(request.URL.absoluteString!) // sets the token in the AuthoriseController
    println("token in AuthoriseController.webView: [\(token)]")
    if(!token.isEmpty) {
        // pass the token to the delegate
        self.delegate?.token = token
        self.dismissViewControllerAnimated(true, completion: nil)
    }
    return true
}