转自:http://www.myexception.cn/swift/1991018.html

前言

Swift 语言,怎么说呢,有一种先接受后排斥,又欢迎的感觉,纵观国外大牛开源框架或项目演示,Swift几乎占据了多半,而国内虽然出现很多相关技术介绍和教程,但是在真正项目开发中使用的占据很少部分,原因一是目前熟练它的开发者并不多,二是版本不太稳定,还需要更成熟可靠的版本支持,但总之未来还是很有前景的,深有体会,不管是代码量还是编译效率,以及语言特性,现代性都优于Object-C,估计后续会被苹果作为官方开发语言,值得期待。

走起

鉴于此,笔者将之前用Object-C写的SSO授权登录:微信,QQ和微博,重新用Swift语言写一遍,以便需要的朋友参考,算是SSO授权登录的姊妹篇;

一、总体架构

1、引入第三方库

除了必须引入对应的登录SDK外,额外引入了SDWebImage,SVProgressHUD,看名字大家都明白吧,引入登录SDK请各自看官方的开发文档,需要加入什么系统库文件,需要配置Other Linker Flags 等,请参考各自官方文档即可;

2、配置连接桥文件

因为创建的工程是基于Swift语言,目前官方SDK和其它三方库都是用OC写的,所以为了在swift中调用oc代码,需要配置连接桥文件Bridging-Header.h,搜索objective-C bridging Header健,然后在值里面输入XXXLogin/Bridging-Header.h,注意是绝对路径,里面可以输入需要调用的头文件,如

#import "WXApi.h"
#import "SVProgressHUD.h"
#import "UIImageView+Webcache.h"

3、配置工程

因为是SSO跳转方式,需要配置URL Schemes,以便程序返回识别宿主程序,配置方法很简单,参考各自文档即可,在info里面可以可视化添加,各自的key值采用官方demo所提供;

二、微信

1、注册

func application(application: UIApplication,didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.

    //向微信注册
    WXApi.registerapp(kWXAPP_ID)

    return true
}

2、授权登录

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addobserver(self,selector:"onRecviceWX_CODE_Notification:",name: "WX_CODE",object: nil)

    let sendBtn:UIButton = UIButton()
    sendBtn.frame = CGRectMake(30,100,kIPHONE_WIDTH-60,40)
    sendBtn.backgroundColor = UIColor.redColor()
    sendBtn.setTitleColor(UIColor.whiteColor(),forState: UIControlState.normal)
    sendBtn.setTitle("Swift版本之微信授权登录",forState: UIControlState.normal)
    sendBtn.addTarget(self,action: "sendBtnClick:",forControlEvents: UIControlEvents.TouchUpInside)
    self.view.addSubview(sendBtn)


    headerImg = UIImageView(frame: CGRectMake(30,160,120,120))
    headerImg.backgroundColor = UIColor.yellowColor()
    self.view.addSubview(headerImg)

    nicknameLbl.frame = CGRectMake(170,kIPHONE_WIDTH-60-140,40)
    nicknameLbl.backgroundColor = UIColor.lightGrayColor()
    nicknameLbl.textColor = UIColor.purpleColor()
    nicknameLbl.textAlignment = NSTextAlignment.Center
    self.view.addSubview(nicknameLbl)
}


func sendBtnClick(sneder:UIButton){
    sendWXAuthRequest()
}

//微信登录 第一步
func sendWXAuthRequest(){
    let req : SendAuthReq = SendAuthReq()
    req.scope = "snsapi_userinfo,snsapi_base"
    WXApi .sendReq(req)
}

3、回调

func onResp(resp: BaseResp!) {
    /* ErrCode ERR_OK = 0(用户同意) ERR_AUTH_DENIED = -4(用户拒绝授权) ERR_USER_CANCEL = -2(用户取消) code 用户换取access_token的code,仅在ErrCode为0时有效 state 第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传,state字符串长度不能超过1K lang 微信客户端当前语言 country 微信用户当前国家信息 */
    // var aresp resp :SendAuthResp!
    var aresp = resp as! SendAuthResp
    // var aresp1 = resp as? SendAuthResp

    if (aresp.errCode == 0)
    {
        println(aresp.code)
        //031076fd11ebfa5d32adf46b37c75aax
        var dic:Dictionary<String,String>=["code":aresp.code];
        let value = dic["code"]
        println("code:\(value)")

        NSNotificationCenter.defaultCenter().postNotificationName("WX_CODE",object: nil,userInfo: dic)
    }
}

4、获取用户信息

//微信回调通知,获取code 第二步
func onRecviceWX_CODE_Notification(notification:NSNotification){
    SVProgressHUD.showSuccessWithStatus("获取到code",duration: 1)
    var userinfoDic : Dictionary = notification.userInfo!
    let code: String = userinfoDic["code"] as! String
    print("Recevice Code: \(code)")
    self.getAccess_token(code)
}

//获取token 第三步
func getAccess_token(code :String){
    //https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
    var requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=\(kWXAPP_ID)&secret=\(kWXAPP_SECRET)&code=\(code)&grant_type=authorization_code"
    dispatch_async(dispatch_get_global_queue(disPATCH_QUEUE_PRIORITY_DEFAULT,0),{
        var requestURL: NSURL = NSURL(string: requestUrl)!
        var data = NSData(contentsOfURL: requestURL,options: NSDataReadingOptions(),error: nil)
        dispatch_async(dispatch_get_main_queue(),{
            var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data!,options: NSJSONReadingOptions.MutableContainers,error: nil) as! NSDictionary
            println("Recevice Token: \(jsonResult)")
            SVProgressHUD.showSuccessWithStatus("获取到Token和openid",duration: 1)
            let token: String = jsonResult["access_token"] as! String
            let openid: String = jsonResult["openid"] as! String
            self.getUserInfo(token,openid: openid)
        })
    })
}

//获取用户信息 第四步
func getUserInfo(token :String,openid:String){
    // https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
    var requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=\(token)&openid=\(openid)"
    dispatch_async(dispatch_get_global_queue(disPATCH_QUEUE_PRIORITY_DEFAULT,error: nil) as! NSDictionary
            print("Recevice UserInfo: \(jsonResult)")
            /* Recevice UserInfo: { city = Chaoyang; country = CN; headimgurl = "http://wx.qlogo.cn/mmopen/FrdAUicrPIibcpGzxuD0kjfssQogj3icL8QTJQYUCLpgzSnvY6rJFGORreicpuiaPCzojwNlsXq4ibbc8e3gGFricWqJU5ia7ibicLVhfT/0"; language = "zh_CN"; nickname = "\U706b\U9505\U6599"; openid = "oyAaTjkR8T6kcKWyA4VPYDa_Wy_w"; privilege = ( ); province = Beijing; sex = 1; unionid = "o1A_Bjg52MglJiEjhLmB8SyYfZIY"; } */

            SVProgressHUD.showSuccessWithStatus("获取到用户信息",duration: 1)
            let headimgurl: String = jsonResult["headimgurl"] as! String
            let nickname: String = jsonResult["nickname"] as! String
            self.headerImg.sd_setimageWithURL(NSURL(string: headimgurl))
            self.nicknameLbl.text = nickname
        })
    })
}

5、跳转

//微信的跳转回调
func application(application: UIApplication,openURL url: NSURL,sourceApplication: String?,annotation: AnyObject?) -> Bool    {
    return  WXApi.handleOpenURL(url,delegate: self)
}
func application(application: UIApplication,handleOpenURL url: NSURL) -> Bool {
    return  WXApi.handleOpenURL(url,delegate: self)
}

三、QQ

1、注册

func sendBtnClick(sneder:UIButton){
    sendQQAuthRequest()
}

//第一步 QQ登录
func sendQQAuthRequest(){
    tencentOAuth = TencentOAuth(appId: kQQAPP_ID,andDelegate: self)
    var permissions = [kOPEN_PERMISSION_GET_INFO,kOPEN_PERMISSION_GET_USER_INFO,kOPEN_PERMISSION_GET_SIMPLE_USER_INFO]
    tencentOAuth.authorize(permissions,inSafari: false)
}

2、授权登录

如上

3、回调

//第二步 登录成功回调
func tencentDidLogin() {
    let accesstoken = tencentOAuth.accesstoken
    println("accesstoken:\(accesstoken)") //641B23508B62392C52D6DFADF67FAA9C
    getUserInfo()
}

//失败
func tencentDidNotLogin(cancelled: Bool) {
    println("登录失败了")
}

//无网络
func tencentDidNotNetWork() {
    println("没有网络")
}

4、获取用户信息

//第三步 获取用户信息
func getUserInfo(){
    SVProgressHUD.showWithStatus("正在获取用户信息...")
    tencentOAuth.getUserInfo()
}


//第四步 在获取用户回调中获取用户信息
func getUserInfoResponse(response: APIResponse!) { 
    SVProgressHUD.dismissWithSuccess("获取用户信息成功",afterDelay: 1)
    var dic:Dictionary = response.jsonResponse
    println("dic:\(dic)")

    //        [is_lost: 0,figureurl: http://qzapp.qlogo.cn/qzapp/222222/C5527A2F775D9EA7C20317128FAC202B/30,vip: 0,is_yellow_year_vip: 0,province: 北京,ret: 0,is_yellow_vip: 0,figureurl_qq_1: http://q.qlogo.cn/qqapp/222222/C5527A2F775D9EA7C20317128FAC202B/40,yellow_vip_level: 0,level: 0,figureurl_1: http://qzapp.qlogo.cn/qzapp/222222/C5527A2F775D9EA7C20317128FAC202B/50,city: 海淀,figureurl_2: http://qzapp.qlogo.cn/qzapp/222222/C5527A2F775D9EA7C20317128FAC202B/100,nickname: 竹中雨滴,msg:,gender: 男,figureurl_qq_2: http://q.qlogo.cn/qqapp/222222/C5527A2F775D9EA7C20317128FAC202B/100]
    refeshUserInfo(dic)
}


//第五步 刷新用户界面
func refeshUserInfo(dic : NSDictionary){
    let headimgurl: String = dic["figureurl_qq_2"] as! String
    let nickname: String = dic["nickname"] as! String 
    self.headerImg.sd_setimageWithURL(NSURL(string: headimgurl))
    self.nicknameLbl.text = nickname
}

5、跳转

func application(application: UIApplication,openURL url: NSURL,annotation: AnyObject?) -> Bool {
    return TencentOAuth.HandleOpenURL(url)
}

func application(application: UIApplication,handleOpenURL url: NSURL) -> Bool {
    return TencentOAuth.HandleOpenURL(url)
}

四、微博

1、注册

func application(application: UIApplication,didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.

    WeiboSDK.registerapp(kAppKey)

    return true
}

2、授权登录

func sendBtnClick(sneder:UIButton){
    sendSinaAuthRequest()
}

//第一步  微博登录
func sendSinaAuthRequest(){
    var request : WBAuthorizeRequest = WBAuthorizeRequest.request() as! WBAuthorizeRequest
    request.redirectURI = kRedirectURI
    request.scope = "all"
    request.userInfo = ["SSO_Key":"SSO_Value"]
    WeiboSDK.sendRequest(request)
}

3、回调

func didReceiveWeiboRequest(request: WBBaseRequest!) {

}

func didReceiveWeiboResponse(response: WBBaseResponse!) {
    if response.isKindOfClass(WBAuthorizeResponse){
        if (response.statusCode == WeiboSDKResponseStatusCode.Success) {
            var authorizeResponse : WBAuthorizeResponse = response as! WBAuthorizeResponse
            var userID = authorizeResponse.userID
            var accesstoken = authorizeResponse.accesstoken
            println("userID:\(userID)\naccesstoken:\(accesstoken)")
            var userInfo = response.userInfo as Dictionary
            NSNotificationCenter.defaultCenter().postNotificationName("SINA_CODE",object: nil,userInfo: userInfo)
        }
    }
}

4、获取用户信息

//第二步 通过通知得到登录后获取的用户信息
func onRecviceSINA_CODE_Notification(notification:NSNotification)
{
    SVProgressHUD.showSuccessWithStatus("获取到用户信息",duration: 1)

    var userinfoDic : Dictionary = notification.userInfo!

    println("userInfo:\(userinfoDic)")


    /* userID:2627289515 accesstoken:2.002BqnrCyY87OC80500cab28Ofqd3B userInfo: [uid: 2627289515,remind_in: 647057,scope: invitation_write,refresh_token: 2.002BqnrCyY87OC10f7877765yPietB,app: { logo = "http://ww1.sinaimg.cn/square/65745bf7jw1ea399us692j2028028glf.jpg"; name = "SDK\U5fae\U535a\U5e94\U7528demo"; },access_token: 2.002BqnrCyY87OC80500cab28Ofqd3B,expires_in: 647057 ] */

    var userAppInfo: Dictionary<String,String> = userinfoDic["app"] as! Dictionary

    refeshUserInfo(userAppInfo)
}

//第三步 刷新用户界面
func refeshUserInfo(dic : NSDictionary){

    let headimgurl: String = dic["logo"] as! String
    let nickname: String = dic["name"] as! String

    self.headerImg.sd_setimageWithURL(NSURL(string: headimgurl))
    self.nicknameLbl.text = nickname
}

5、跳转

func application(application: UIApplication,annotation: AnyObject?) -> Bool {
    return WeiboSDK.handleOpenURL(url,delegate: self)
}

func application(application: UIApplication,handleOpenURL url: NSURL) -> Bool {
    return WeiboSDK.handleOpenURL(url,delegate: self)
}

五、对比分析

1、demo情况

微博demo代码工整度完爆微信,QQ,看着很舒服,心情也不错;另外微博放在了github上面,适合pod管理,注释也极好,微信文档写的挺不错,QQ写的简直丧心病狂,需要极度耐心才能看明白,表示很无语,另外本三种方式授权登录的源代码有偿提供,如需可以邮件mmw05@163.com即可;

2、嵌入时间

微信算是很容易嵌入SDK,QQ也还可以,微博需要注意boundID有限制,微信的逻辑算是比较冗余繁琐,从授权到获取到用户信息需要很多接口,而QQ和微博可以直接从授权登陆回调中获取到,是比较便捷的,从上面代码可以看出来;

后记

从objective-C到Swift,苹果力求简约,但又不简单,现代化的语言,必然在性能各方面优于传统,只是需要时间和更多的考验,作为开发者,多一个选择,岂不更好!
附图:

基于Swift语言开发微信、QQ跟微博的SSO授权登录代码分析的更多相关文章

  1. 详解如何通过H5(浏览器/WebView/其他)唤起本地app

    这篇文章主要介绍了详解如何通过H5(浏览器/WebView/其他)唤起本地app的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. HTML5 WebSocket实现点对点聊天的示例代码

    这篇文章主要介绍了HTML5 WebSocket实现点对点聊天的示例代码的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

  4. ios – Trello iPhone应用程序是如何开发的?

    我想知道Trelloiphone应用程序正在使用哪些库或框架.它是一个JS框架的webapp?我很好奇,因为我非常喜欢用户界面,并且在没有运气的情况下搜索了互联网.解决方法我在Trello团队中编写了iPhone应用程序.它是除了附件查看器之外的所有本机代码,它只是一个WebView.我们使用RestKit与我们的API进行通信,并帮助将数据本地缓存到CoreData.否则,它只是一堆自定义UIViews和UIViewControllers.

  5. ios – 在Swift中将输入字段字符串转换为Int

    所以我非常擅长制作APP广告Swift,我试图在文本字段中做一些非常简单的输入,取值,然后将它们用作Int进行某些计算.但是’vardistance’有些东西不正确它是导致错误的最后一行代码.它说致命错误:无法解开Optional.None解决方法在你的例子中,距离是一个Int?否则称为可选的Int..toInt()返回Int?因为从String到Int的转换可能失败.请参阅以下示例:

  6. 如何在iOS中检测文本(字符串)语言?

    例如,给定以下字符串:我想检测每个声明的字符串中使用的语言.让我们假设已实现函数的签名是:如果没有检测到语言,则返回可选字符串.因此,适当的结果将是:有一个简单的方法来实现它吗?

  7. xamarin – 崩溃在AccountStore.Create().保存(e.Account,“);

    在Xamarin.Forms示例TodoAwsAuth中https://developer.xamarin.com/guides/xamarin-forms/web-services/authentication/oauth/成功登录后,在aOnAuthenticationCompleted事件中,应用程序在尝试保存到Xamarin.Auth时崩溃错误说不能对钥匙串说期待着寻求帮助.解决方法看看你

  8. ios – 将视频分享到Facebook

    我正在编写一个简单的测试应用程序,用于将视频从iOS上传到Facebook.由于FacebookSDK的所有文档都在Objective-C中,因此我发现很难在线找到有关如何使用Swift执行此操作的示例/教程.到目前为止我有这个在我的UI上放置一个共享按钮,但它看起来已禁用,从我读到的这是因为没有内容设置,但我看不出这是怎么可能的.我的getVideoURL()函数返回一个NSURL,它肯定包含视

  9. xcode – 错误“线程1:断点2.1”

    我正在研究RESTAPI管理器.这是一个错误,我无法解决它.我得到的错误在下面突出显示.当我打电话给这个班级获取资源时:我评论的线打印:Thread1:breakpoint2.1我需要修复错误的建议.任何建议都非常感谢解决方法您可能在不注意的情况下意外设置了断点.单击并拖动代表断路器外部断点的蓝色刻度线以将其擦除.

  10. ios-您的应用是否包含,显示或访问第三方内容? AdMob广告

    虽然在itunes上提交了一个app,它集成了admob,但复选框“你的应用是否包含,显示或访问第三方内容?”的价值应该是什么?解决方法答案是否定的,不要检查它,而你必须检查你的应用程序是否正在使用IDFA,并确保选中“在应用程序内投放广告”.

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部