前言:
今天主要實(shí)現(xiàn)OAuth2.0登錄和自定義的歸檔。用到的第三方和知識
1距帅、指示器 SVProgressHUD
2抖仅、網(wǎng)絡(luò)請求第三方Alamofire
3、OAuth2.0微博開放平臺
4咏窿、自定義對象的歸檔和解檔
首先看下實(shí)現(xiàn)的簡單效果
1斟或、OAuth2.0授權(quán)的機(jī)制如下圖
實(shí)現(xiàn)步驟
1、加載授權(quán)頁面(獲取code)
2集嵌、通過code后期accessToken
3萝挤、通過accessToken去獲取用戶的信息
采用webView來加載授權(quán)頁面
首先懶加載一個webView并遵守代理
//MARK:懶加載
lazy var webView:UIWebView = {
let webView = UIWebView()
webView.delegate = self
return webView
}()
定義一些常量
let ReBackURL:String = "https://api.weibo.com/oauth2/default.html" // 回調(diào)的URL
let AppKey:String = "2100191772" // 程序appkey
let AppSecret:String = "20701cb27e6279060eae21c1a7522f8c" // APPSecret
注意:這里需要成為新浪的開放者,并且新建自己的應(yīng)用根欧,才有上面的信息怜珍。我就不在這里詳細(xì)描述了。微博開放平臺
加載web view
let urlString = "https://api.weibo.com/oauth2/authorize?client_id=\(AppKey)&redirect_uri=\(ReBackURL)";
let url = NSURL(string: urlString)
let request = NSURLRequest(URL: url!)
webView.loadRequest(request)
獲取和獲取accessToken主要下下面的代理方法中實(shí)現(xiàn),攔截URL
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
let urlString:String = request.URL!.absoluteString
if !urlString.hasPrefix(ReBackURL) {
//如果不是回調(diào)Url就繼續(xù)加載
return true
}
// 判斷是否授權(quán)成功
let parameterStr = "code="
if request.URL!.query!.hasPrefix(parameterStr) {
//授權(quán)成功,取出code的參數(shù)用于
print(request.URL!.query!)
let code = request.URL!.query!.substringFromIndex(parameterStr.endIndex)
// 獲取accessToken
requestAccessToken(code)
}
else {
navigationController?.popViewControllerAnimated(true)
}
return false
}
獲取accessToken的方法實(shí)現(xiàn)如下
private func requestAccessToken(code:String){
//
let accessTokenPath = "https://api.weibo.com/oauth2/access_token"
// 參數(shù)
let params = ["client_id":AppKey,"client_secret":AppSecret,"grant_type":"authorization_code","code":code,"redirect_uri":ReBackURL]
Alamofire.request(.POST, accessTokenPath, parameters: params, encoding: .URL, headers: nil).responseJSON { (response) in
print(response.request)
print(response.response)
print(response.data)
print(response.result)
if let json = response.result.value {
print("json\(json)")
let userAccount = YJUserAccount(dict: json as![String:AnyObject])
print(userAccount.access_token)
userAccount.loginSuccess = true
userAccount.savaAccount()
//獲取accessToken成功凤粗,證明登錄成功了
let base = YJBaseTabBarViewController()
base.selectedIndex = 1
UIApplication.sharedApplication().keyWindow?.rootViewController = base
SVProgressHUD.showInfoWithStatus("登錄成功")
}
}
}
通過上一步的code酥泛,去換取accessToken,請求成功后返回JSON數(shù)據(jù)嫌拣,我們自定義一個Model去解析柔袁,并保存到本地。
定義的模型YJUserAccount
class YJUserAccount: NSObject,NSCoding
要對自定義的對象實(shí)現(xiàn)歸檔和解檔异逐,需要遵守NSCoding協(xié)議并實(shí)現(xiàn)下面的兩個方法
//MARK:NSCoding
func encodeWithCoder(aCoder: NSCoder) {
/* var access_token:String? // 令牌
var expires_in:NSNumber? // 過期時間戳
var uid: NSNumber? // 用戶ID
var loginSuccess:Bool = false // 是否登錄成功*/
aCoder.encodeObject(access_token, forKey: "access_token")
aCoder.encodeObject(expires_in, forKey: "expires_in")
aCoder.encodeObject(uid, forKey: "uid")
aCoder.encodeBool(loginSuccess, forKey: "loginSuccess")
}
required init?(coder aDecoder: NSCoder) {
access_token = aDecoder.decodeObjectForKey("access_token") as? String
expires_in = aDecoder.decodeObjectForKey("expires_in") as? NSNumber
uid = aDecoder.decodeObjectForKey("uid") as? NSNumber
loginSuccess = aDecoder.decodeBoolForKey("loginSuccess")
}
另外一注意一點(diǎn)就是字典轉(zhuǎn)模型的捶索,有些字沒有,會出現(xiàn)崩潰的情況灰瞻,可以改下下面的方法情组,就不會崩潰了。
//為了不讓其崩潰箩祥,重寫該
override func setValue(value: AnyObject?, forUndefinedKey key: String) {
}
歸檔和解檔方法實(shí)現(xiàn)
// 歸檔
internal func savaAccount() {
let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).last
if let savePath = path {
let archievePath = savePath.stringByAppendingString("/account.plist")
print(archievePath)
if NSKeyedArchiver.archiveRootObject(self, toFile: archievePath)
{
print("歸檔成功")
}
}
}
// 解檔
internal class func loadAccount() -> YJUserAccount? {
let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).last
let archievePath = path!.stringByAppendingString("/account.plist")
let userAccoutn = NSKeyedUnarchiver.unarchiveObjectWithFile(archievePath) as? YJUserAccount
return userAccoutn
}
上面就是簡單的實(shí)現(xiàn)思路院崇。