• IOS开发学习日记(十七)


    简单的第三方登录和分享功能

    第三方登录系统

    ·URL Scheme:App间的跳转及通信

    ·App间跳转场景

    ·登陆系统:

            ·跨平台,跨App

            ·标记用户,个性化的推送

            ·使用第三方登录(减少注册成本 / 无须维护敏感信息

            ·微信 / QQ / 微博 / facebook / Twitter

    ·登录系统通用技术

            ·framework的使用和集成

            ·常用的第三方认证和账户体系

            ·业务逻辑的设计和实现

    静态库 & 动态库

            ·库Library

                    ·代码共享 / 保护核心代码

                    ·提高编译速度 / 减少代码提及(系统)

            ·静态库

                    ·.a文件

                    ·编译时期拷贝

                    ·增大代码提及 / 不可改变

            ·动态库

                    ·.dylib

                    ·编译时期只存储引用,运行时加载到内存

                    ·无须拷贝减少体积 / 性能损失 / 安全性

     IOS中静态库的创建和使用

    ·Framework

            ·资源的打包方式

            ·支持静态库 / 动态库

            ·系统的Framework都是动态库

            ·支持Extension共享 - Embedded framework

    静态库的制作:

            ·创建static Library实现业务逻辑

            ·设置需要暴露的头文件

            ·模拟器 / 设备分别编译 / 设置Settings

            ·合并静态库lipo - create ***.a ***.a -output ***.a

    ·静态库(.a)本身是二进制文件

    ·需要手动引入头文件使用

    ·一般需要设置Other Linker Flags等

    IOS中Framework的制作和使用

    ·创建framework实现业务逻辑

    ·设置public的头文件

    ·模拟器 / 设备 / 分别编译 / 设置Settings

    ·合并framework

    ·引入framework 即包含头文件

    ·头文件的引入

    ·一般需要设置Other Linker Flags等

    OAuth & OpenID 

    OAuth授权

            ·第三方登录使用用户名 / 密码(安全 / 用户成本)

            ·开放协议,标准的方式去访问需要用户授权的API服务

    OpenID

            ·明文的安全性 / 不同的业务,无法隔离

            ·隐藏明文 / 每个App独立的openID

    集成QQ SDK实现登录和分享功能

    首先下载TencentOpenApi,在podfile中添加:

    1. # pod TencentOpenAPI
    2. pod 'TencentOpenAPI', :git => 'https://github.com/everfire130/TencentOpenAPI.git'

    或者在腾讯开放平台中下载SDK:SDK下载 — QQ互联WIKI 

    1. //
    2. // GSCLogin.h
    3. // GSCApp1
    4. //
    5. // Created by gsc on 2024/6/22.
    6. //
    7. #import
    8. NS_ASSUME_NONNULL_BEGIN
    9. typedef void(^GSCLoginFinishBlock)(BOOL isLogin);
    10. @interface GSCLogin : NSObject
    11. @property(nonatomic,strong,readonly)NSString *nick;
    12. @property(nonatomic,strong,readonly)NSString *address;
    13. @property(nonatomic,strong,readonly)NSString *avatarUrl;
    14. +(instancetype)sharedLogin;
    15. #pragma - mark - 登录
    16. -(BOOL)isLogin;
    17. -(void)loginWithFinishBlock:(GSCLoginFinishBlock)finishBlock;
    18. -(void)logOut;
    19. #pragma - mark - 分享
    20. -(void)shareToQQWithArticleUrl:(NSURL *)articleUrl;
    21. //
    22. // GSCLogin.m
    23. // GSCApp1
    24. //
    25. // Created by gsc on 2024/6/22.
    26. //
    27. #import "GSCLogin.h"
    28. #import "TencentOpenAPI/QQApiInterface.h"
    29. #import "TencentOpenAPI/TencentOAuth.h"
    30. @interface GSCLogin () <TencentSessionDelegate>
    31. @property (nonatomic, strong, readwrite) TencentOAuth *oauth;
    32. @property (nonatomic, copy, readwrite) GSCLoginFinishBlock finishBlock;
    33. @property (nonatomic, assign, readwrite) BOOL isLogin;
    34. @end
    35. @implementation GSCLogin
    36. +(instancetype)sharedLogin{
    37. static GSCLogin *login;
    38. static dispatch_once_t onceToken;
    39. dispatch_once(&onceToken, ^{
    40. login = [[GSCLogin alloc] init];
    41. });
    42. return login;
    43. }
    44. -(instancetype)init{
    45. self = [super init];
    46. if(self){
    47. _isLogin = NO;
    48. _oauth = [[TencentOAuth alloc] initWithAppId:@"123456" andDelegate:self];
    49. }
    50. return self;
    51. }
    52. #pragma - mark - 登录
    53. -(BOOL)isLogin{
    54. return _isLogin;
    55. }
    56. -(void)loginWithFinishBlock:(GSCLoginFinishBlock)finishBlock{
    57. _finishBlock = [finishBlock copy];
    58. _oauth.authMode = kAuthModeClientSideToken;
    59. [_oauth authorize:@[kOPEN_PERMISSION_GET_USER_INFO,
    60. kOPEN_PERMISSION_GET_SIMPLE_USER_INFO,
    61. kOPEN_PERMISSION_ADD_ALBUM,
    62. kOPEN_PERMISSION_ADD_TOPIC,
    63. kOPEN_PERMISSION_CHECK_PAGE_FANS,
    64. kOPEN_PERMISSION_GET_INFO,
    65. kOPEN_PERMISSION_GET_OTHER_INFO,
    66. kOPEN_PERMISSION_LIST_ALBUM,
    67. kOPEN_PERMISSION_UPLOAD_PIC,
    68. kOPEN_PERMISSION_GET_VIP_INFO,
    69. kOPEN_PERMISSION_GET_VIP_RICH_INFO]];
    70. }
    71. -(void)logOut{
    72. [_oauth logout:self];
    73. _isLogin = NO;
    74. }
    75. #pragma mark - delegate
    76. -(void)tencentDidLogin{
    77. _isLogin = YES;
    78. [_oauth getUserInfo];
    79. }
    80. -(void)tencentDidNotLogin:(BOOL)cancelled{
    81. if(_finishBlock){
    82. _finishBlock(NO);
    83. }
    84. }
    85. -(void)tencentDidNotNetWork{
    86. }
    87. -(void)tencentDidLogout{
    88. }
    89. -(void)getUserInfoResponse:(APIResponse *)response{
    90. NSDictionary *userInfo = response.jsonResponse;
    91. _nick = userInfo[@"nickname"];
    92. _address = userInfo[@"city"];
    93. _avatarUrl = userInfo[@"figureurl_qq_2"];
    94. if(_finishBlock){
    95. _finishBlock(YES);
    96. }
    97. }
    98. #pragma - mark - 分享
    99. -(void)shareToQQWithArticleUrl:(NSURL *)articleUrl{
    100. QQApiNewsObject *newsObj = [QQApiNewsObject objectWithURL:articleUrl title:@"ios" description:@"iosDevLearn" previewImageURL:nil];
    101. SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:newsObj];
    102. __unused QQApiSendResultCode sent = [QQApiInterface SendReqToQZone:req];
    103. }
    104. @end
    105. @end
    106. NS_ASSUME_NONNULL_END
    1. //
    2. // GSCMineViewController.m
    3. // GSCApp1
    4. //
    5. // Created by gsc on 2024/6/22.
    6. //
    7. #import "GSCMineViewController.h"
    8. #import "GSCLogin.h"
    9. #import "SDWebImage/SDWebImage.h"
    10. @interface GSCMineViewController ()<UITableViewDelegate, UITableViewDataSource>
    11. @property (nonatomic, strong, readwrite) UITableView *tableView;
    12. @property (nonatomic, strong, readwrite) UIView *tableViewHeaderView;
    13. @property (nonatomic, strong, readwrite) UIImageView *headerImageView;
    14. @end
    15. @implementation GSCMineViewController
    16. -(instancetype)init{
    17. self = [super init];
    18. if(self){
    19. self.tabBarItem.title = @"我的";
    20. self.tabBarItem.image = [UIImage imageNamed:@"icon.bundle/home@2x.png"];
    21. self.tabBarItem.selectedImage = [UIImage imageNamed:@"icon.bundle/home_selected@2x.png"];
    22. }
    23. return self;
    24. }
    25. - (void)viewDidLoad {
    26. [super viewDidLoad];
    27. self.view.backgroundColor = [UIColor whiteColor];
    28. [self.view addSubview:({
    29. _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
    30. _tableView.delegate = self;
    31. _tableView.dataSource = self;
    32. _tableView;
    33. })];
    34. }
    35. #pragma mark - Navigation
    36. -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    37. return 2;
    38. }
    39. -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    40. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"mineTableViewCell"];
    41. if(!cell){
    42. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"mineTableView"];
    43. }
    44. return cell;
    45. }
    46. -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    47. return 60;
    48. }
    49. -(nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    50. if(!_tableViewHeaderView){
    51. _tableViewHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 30, self.view.frame.size.width, self.view.frame.size.height)];
    52. _tableViewHeaderView.backgroundColor = [UIColor whiteColor];
    53. [_tableViewHeaderView addSubview:({
    54. _headerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 30, self.view.frame.size.width, self.view.frame.size.height)];
    55. _headerImageView.backgroundColor = [UIColor whiteColor];
    56. _headerImageView.contentMode = UIViewContentModeScaleAspectFit;
    57. _headerImageView.clipsToBounds = YES;
    58. _headerImageView.userInteractionEnabled = YES;
    59. _headerImageView;
    60. })];
    61. [_tableViewHeaderView addGestureRecognizer:({
    62. UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_tapImage)];
    63. tapGesture;
    64. })];
    65. }
    66. return _tableViewHeaderView;
    67. }
    68. -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    69. return 200;
    70. }
    71. -(void)tableView:(UITableView *)tableView willDisplayHeaderView:(nonnull UIView *)view forSection:(NSInteger)section{
    72. if(![[GSCLogin sharedLogin] isLogin]){
    73. [_headerImageView setImage:[UIImage imageNamed:@"icon.bundle/prettydog.png"]];
    74. }else{
    75. [self.headerImageView sd_setImageWithURL:[NSURL URLWithString:[GSCLogin sharedLogin].avatarUrl]];
    76. }
    77. }
    78. -(void)tableView:(UITableView *)tableView willDisplayCell:(nonnull UITableViewCell *)cell forRowAtIndexPath:(nonnull NSIndexPath *)indexPath{
    79. if(indexPath.row == 0){
    80. cell.textLabel.text = [[GSCLogin sharedLogin] isLogin] ? [GSCLogin sharedLogin].nick: @"昵称";
    81. }else{
    82. cell.textLabel.text = [[GSCLogin sharedLogin] isLogin] ? [GSCLogin sharedLogin].address:@"地区";
    83. }
    84. }
    85. #pragma mark -
    86. -(void)_tapImage{
    87. __weak typeof(self) weakSelf = self;
    88. if(![[GSCLogin sharedLogin] isLogin]){
    89. // 如果未登录则拉起登录
    90. [[GSCLogin sharedLogin] loginWithFinishBlock:^(BOOL isLogin){
    91. __strong typeof(self) strongSelf = self;
    92. if(isLogin){
    93. [strongSelf.tableView reloadData];
    94. }
    95. }];
    96. }else{
    97. // 已登录则退出登录
    98. [[GSCLogin sharedLogin] logOut];
    99. [self.tableView reloadData];
    100. }
    101. }
    102. @end

    集成SDK实现登录与分享:

            ·申请接入,获取appid和apikey

            ·集成SDK设置对应的settings及URL Scheme

            ·业务逻辑的基础UI和交互(登录 / 分享 ...)

            ·通过用户登录验证和授权,获取Access Token

            ·通过Access Token获取用户的OpenID

            ·通过OpenAPI请求访问或修改用户授权的资源

            ·客户端保存相应用户信息,按需展示

            ·调用其它API实现分享等逻辑

  • 相关阅读:
    【Qt】开发环境搭建
    API网关是什么?
    机器学习--Transformer 1
    视频产品介绍:AS-VCVR-N多协议视频接入网关
    2022 年 JavaScript 开发工具的生态,别再用过时的框架了
    黑客零基础入门教程及方法,从零开始学习黑客技术,看这一篇就够了
    vue3实现数据大屏内数据向上滚动,鼠标进入停止滚动 vue3+Vue3SeamlessScroll
    【Unity实战】手戳一个自定义角色换装系统——2d3d通用
    Python: 每日一题之第几个幸运数字
    基于Vue+Nodejs实现医药商城销售系统
  • 原文地址:https://blog.csdn.net/gsc711/article/details/139865148