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中添加:
# pod TencentOpenAPI
pod 'TencentOpenAPI', :git => 'https://github.com/everfire130/TencentOpenAPI.git'
或者在腾讯开放平台中下载SDK:SDK下载 — QQ互联WIKI
//
// GSCLogin.h
// GSCApp1
//
// Created by gsc on 2024/6/22.
//#import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGINtypedef void(^GSCLoginFinishBlock)(BOOL isLogin);@interface GSCLogin : NSObject@property(nonatomic,strong,readonly)NSString *nick;
@property(nonatomic,strong,readonly)NSString *address;
@property(nonatomic,strong,readonly)NSString *avatarUrl;+(instancetype)sharedLogin;#pragma - mark - 登录-(BOOL)isLogin;
-(void)loginWithFinishBlock:(GSCLoginFinishBlock)finishBlock;
-(void)logOut;#pragma - mark - 分享
-(void)shareToQQWithArticleUrl:(NSURL *)articleUrl;//
// GSCLogin.m
// GSCApp1
//
// Created by gsc on 2024/6/22.
//#import "GSCLogin.h"
#import "TencentOpenAPI/QQApiInterface.h"
#import "TencentOpenAPI/TencentOAuth.h"@interface GSCLogin () <TencentSessionDelegate>@property (nonatomic, strong, readwrite) TencentOAuth *oauth;
@property (nonatomic, copy, readwrite) GSCLoginFinishBlock finishBlock;
@property (nonatomic, assign, readwrite) BOOL isLogin;@end@implementation GSCLogin+(instancetype)sharedLogin{static GSCLogin *login;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{login = [[GSCLogin alloc] init];});return login;
}-(instancetype)init{self = [super init];if(self){_isLogin = NO;_oauth = [[TencentOAuth alloc] initWithAppId:@"123456" andDelegate:self];}return self;
}
#pragma - mark - 登录-(BOOL)isLogin{return _isLogin;
}
-(void)loginWithFinishBlock:(GSCLoginFinishBlock)finishBlock{_finishBlock = [finishBlock copy];_oauth.authMode = kAuthModeClientSideToken;[_oauth authorize:@[kOPEN_PERMISSION_GET_USER_INFO,kOPEN_PERMISSION_GET_SIMPLE_USER_INFO,kOPEN_PERMISSION_ADD_ALBUM,kOPEN_PERMISSION_ADD_TOPIC,kOPEN_PERMISSION_CHECK_PAGE_FANS,kOPEN_PERMISSION_GET_INFO,kOPEN_PERMISSION_GET_OTHER_INFO,kOPEN_PERMISSION_LIST_ALBUM,kOPEN_PERMISSION_UPLOAD_PIC,kOPEN_PERMISSION_GET_VIP_INFO,kOPEN_PERMISSION_GET_VIP_RICH_INFO]];}
-(void)logOut{[_oauth logout:self];_isLogin = NO;
}#pragma mark - delegate-(void)tencentDidLogin{_isLogin = YES;[_oauth getUserInfo];
}-(void)tencentDidNotLogin:(BOOL)cancelled{if(_finishBlock){_finishBlock(NO);}
}-(void)tencentDidNotNetWork{}-(void)tencentDidLogout{}-(void)getUserInfoResponse:(APIResponse *)response{NSDictionary *userInfo = response.jsonResponse;_nick = userInfo[@"nickname"];_address = userInfo[@"city"];_avatarUrl = userInfo[@"figureurl_qq_2"];if(_finishBlock){_finishBlock(YES);}
}
#pragma - mark - 分享
-(void)shareToQQWithArticleUrl:(NSURL *)articleUrl{QQApiNewsObject *newsObj = [QQApiNewsObject objectWithURL:articleUrl title:@"ios" description:@"iosDevLearn" previewImageURL:nil];SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:newsObj];__unused QQApiSendResultCode sent = [QQApiInterface SendReqToQZone:req];
}@end@endNS_ASSUME_NONNULL_END
//
// GSCMineViewController.m
// GSCApp1
//
// Created by gsc on 2024/6/22.
//#import "GSCMineViewController.h"
#import "GSCLogin.h"
#import "SDWebImage/SDWebImage.h"@interface GSCMineViewController ()<UITableViewDelegate, UITableViewDataSource>@property (nonatomic, strong, readwrite) UITableView *tableView;
@property (nonatomic, strong, readwrite) UIView *tableViewHeaderView;
@property (nonatomic, strong, readwrite) UIImageView *headerImageView;@end@implementation GSCMineViewController-(instancetype)init{self = [super init];if(self){self.tabBarItem.title = @"我的";self.tabBarItem.image = [UIImage imageNamed:@"icon.bundle/home@2x.png"];self.tabBarItem.selectedImage = [UIImage imageNamed:@"icon.bundle/home_selected@2x.png"];}return self;
}- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor whiteColor];[self.view addSubview:({_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];_tableView.delegate = self;_tableView.dataSource = self;_tableView;})];
}#pragma mark - Navigation-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{return 2;
}-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"mineTableViewCell"];if(!cell){cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"mineTableView"];}return cell;
}-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{return 60;
}-(nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{if(!_tableViewHeaderView){_tableViewHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 30, self.view.frame.size.width, self.view.frame.size.height)];_tableViewHeaderView.backgroundColor = [UIColor whiteColor];[_tableViewHeaderView addSubview:({_headerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 30, self.view.frame.size.width, self.view.frame.size.height)];_headerImageView.backgroundColor = [UIColor whiteColor];_headerImageView.contentMode = UIViewContentModeScaleAspectFit;_headerImageView.clipsToBounds = YES;_headerImageView.userInteractionEnabled = YES;_headerImageView;})];[_tableViewHeaderView addGestureRecognizer:({UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_tapImage)];tapGesture;})];}return _tableViewHeaderView;
}-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{return 200;
}-(void)tableView:(UITableView *)tableView willDisplayHeaderView:(nonnull UIView *)view forSection:(NSInteger)section{if(![[GSCLogin sharedLogin] isLogin]){[_headerImageView setImage:[UIImage imageNamed:@"icon.bundle/prettydog.png"]];}else{[self.headerImageView sd_setImageWithURL:[NSURL URLWithString:[GSCLogin sharedLogin].avatarUrl]];}
}-(void)tableView:(UITableView *)tableView willDisplayCell:(nonnull UITableViewCell *)cell forRowAtIndexPath:(nonnull NSIndexPath *)indexPath{if(indexPath.row == 0){cell.textLabel.text = [[GSCLogin sharedLogin] isLogin] ? [GSCLogin sharedLogin].nick: @"昵称";}else{cell.textLabel.text = [[GSCLogin sharedLogin] isLogin] ? [GSCLogin sharedLogin].address:@"地区";}}#pragma mark --(void)_tapImage{__weak typeof(self) weakSelf = self;if(![[GSCLogin sharedLogin] isLogin]){// 如果未登录则拉起登录[[GSCLogin sharedLogin] loginWithFinishBlock:^(BOOL isLogin){__strong typeof(self) strongSelf = self;if(isLogin){[strongSelf.tableView reloadData];}}];}else{// 已登录则退出登录[[GSCLogin sharedLogin] logOut];[self.tableView reloadData];}
}@end
集成SDK实现登录与分享:
·申请接入,获取appid和apikey
·集成SDK设置对应的settings及URL Scheme
·业务逻辑的基础UI和交互(登录 / 分享 ...)
·通过用户登录验证和授权,获取Access Token
·通过Access Token获取用户的OpenID
·通过OpenAPI请求访问或修改用户授权的资源
·客户端保存相应用户信息,按需展示
·调用其它API实现分享等逻辑
相关文章:
IOS开发学习日记(十七)
简单的第三方登录和分享功能 第三方登录系统 URL Scheme:App间的跳转及通信 App间跳转场景 登陆系统: 跨平台,跨App 标记用户,个性化的推送 使用第三方登录(减少注册成本 / 无须维护敏感信息) 微信 / Q…...
【ARMv8/ARMv9 硬件加速系列 2 -- ARM NEON 加速运算介绍】
文章目录 ARM NEONNEON 向量寄存器NEON 寄存器使用方式NEON 寄存器的视图NEON 寄存器别名NEON 寄存器的用途ARM NEON 在ARMv8架构中,引入了一组新的寄存器,称为向量寄存器(Vector Registers),用于支持高效的向量和浮点计算。这些寄存器是SIMD(Single Instruction, Multi…...
LayoutSystem布局系统
简介: LayoutSystem,是UGUI中由CanvasUpdateSystem发起(m_LayoutRebuildQueue中大部分都是LayoutRebuilder)的关于布局排列的处理系统。 类图: 布局过程 核心代码讲解: LayoutRebuilder...
滚球游戏笔记
1、准备工作 (1) 创建地面:3D Object-Plane,命名为Ground (2) 创建小球:3D Object-sphere,命名为Player,PositionY 0.5。添加Rigidbody组件 (3) 创建文件夹:Create-Foder,分别命名为Material…...
Mysql8死锁排查
Mysql8死锁排查 Mysql8 查询死锁的表 -- 查询死锁表select * from performance_schema.data_locks;-- 查询死锁等待时间select * from performance_schema.data_lock_waits;Mysql8之前的版本 查询死锁的表 -- 查询死锁表SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;-- 查询…...
程序猿成长之路之数据挖掘篇——决策树分类算法(1)——信息熵和信息增益
决策树不仅在人工智能领域发挥着他的作用,而且在数据挖掘中也在分类领域中独占鳌头。了解决策树的思想是学习数据挖掘中的分类算法的关键,也是学习分类算法的基础。 什么是决策树 用术语来说,决策树(Decision Tree)是…...
数据通信与网络(五)
交换机功能: 地址学习(端口/MAC地址映射表) 通信过滤(基于端口/MAC地址映射表) 生成树协议(断开环路) 隔离冲突域 生成树协议 隔离冲突域 交换机配置模式(用不同级别的命令对交换机进行配置) 普…...
数据中心容灾考题
abc cd abc c为啥...
win10远程桌面连接端口,远Win10远程桌面连接端口修改及无法连接解决方案
一、Win10远程桌面连接端口概述 Win10远程桌面连接功能允许用户从远程位置访问和控制另一台计算机。远程桌面连接默认使用TCP 3389端口,但出于安全或其他需求,用户可能希望修改此端口。 二、Win10远程桌面连接端口修改方法 要修改Win10远程桌面连接的…...
基于AT89C52单片机的温度报警系统
点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/89456321?spm=1001.2014.3001.5503 仿真构造:AT89C52+DS18B20温度模块+三按键+蜂鸣器+四位数码管显示+电源模块。 压缩包构造:源码+仿真图+设计文档+原理图+开题文档+元件…...
[保姆级教程]uniapp配置vueX
文章目录 注意新建文件简单的使用 注意 uniapp是支持vueX的只需配置一下就好 新建文件 在src文件中,新建一个store(如果有的话跳过) 在store中新建一个js文件,修改js文件名称和选择模板为default 在 uni-app 项目根目录下&…...
第二次IAG
IAG in NanJing City 我与南京奥体的初次相遇,也可能是最后一次! 对我来说,IAG 演唱会圆满结束啦! 做了两场充满爱[em]e400624[/em]的美梦 3.30号合肥站,6.21号南京站[em]e400947[/em] 其实,没想到昨天回去看呀!(lack of money […...
智慧校园综合管理系统的优点有哪些
在当今这个信息化飞速发展的时代,智慧校园综合管理系统正逐步成为教育领域的一股革新力量,它悄然改变着我们对传统校园管理的认知。这套系统如同一个无形的桥梁,将先进的信息技术与学校的日常运作紧密相连,展现出多维度的优势。 …...
如何跳出认知偏差,个人认知能力升级
一、教程描述 什么是认知力?认知力(cognitive ability),实际上就是指一个人的认知能力,是指人的大脑加工、储存和提取信息的能力,或者主观对非主观的事物的反映能力,如果变成大白话,…...
Scala中的map函数
Scala中的map函数 在 Scala 中,map 是一种常见的高阶函数,用于对集合中的每个元素应用一个函数,并返回应用了该函数后的新集合,保持原始集合的结构不变。它的主要作用有以下几点: 1. 遍历集合: map 可以遍历…...
linux安装conda环境实践
Conda介绍 conda 是一个开源的软件包管理系统和环境管理软件,用于安装多个版本的软件包及其依赖关系,并在它们之间轻松切换。 conda 分为 anaconda 和 miniconda,anaconda 是一个包含了许多常用库的集合版本,miniconda 是精简版…...
Flutter-实现头像叠加动画效果
实现头像叠加动画效果 在这篇文章中,我们将介绍如何使用 Flutter 实现一个带有透明度渐变效果和过渡动画的头像叠加列表。通过这种效果,可以在图片切换时实现平滑的动画,使 UI 更加生动和吸引人。 需求 我们的目标是实现一个头像叠加列表&…...
MSPM0G3507——特殊的串口0
在烧录器中有串口0,默认也是串口0通过烧录线给电脑发数据。 如果要改变,需要变一下LP上的跳线帽。 需要更改如下位置的跳线帽...
如何选择合适的大模型框架:LangChain、LlamaIndex、Haystack 还是 Hugging Face
节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学。 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 合集&#x…...
TCP 协议详解:三次握手与四次挥手
在网络通信中,确保数据准确无误地传递是至关重要的。TCP(Transmission Control Protocol,传输控制协议)作为一种面向连接的、可靠的、基于字节流的通信协议,在网络数据传输中起到了核心作用。本文将详细解析 TCP 的基本…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
