当前位置: 首页 > news >正文

iOS开发-检查版本更新与强制更新控制

iOS开发-检查版本更新与强制更新控制。

在开发中经常遇到需要检查版本,检查版本及请求appstoreLookUrl查看版本号与当前的版本号进行比对,看是否需要更新。强制更新控制,是将获取到当前版本号传给服务端,服务端判断当前的版本是否需要强制升级。

一、app升级检查

发送请求系统NSURLConnection sendAsynchronousRequest

代码如下

SDVersionManager.h

#import <Foundation/Foundation.h>@interface SDVersionManager : NSObject<NSCoding>@property (nonatomic,strong) NSString *lastVersionCode; //版本code@property (nonatomic,strong) NSString *lastVersion;     //保存最新的版本lastVersion@property (nonatomic,strong) NSString *versionNotes;    //版本更新的记录releaseNotes+ (instancetype)sharedInstance;/**检测版本更新,如果有新版本,提醒用户更新,提醒一次@param needUpdate 需要更新的回调@param failure 不需要更新*/
+ (void)checkAppVersion:(void (^) (void))needUpdatefailure:(void (^) (void))failure;@end#pragma mark - SDVersionManagerDB@interface SDVersionManagerDB : NSObject+ (instancetype)sharedInstance;/**获取自定义对象UpdatedVersion实体,反序列化操作@return UpdatedVersion 实体*/
- (SDVersionManager *)loadLastVersion;/**保存自定义对象序列号@param version UpdatedVersion实体@return 是否保存成功*/
- (BOOL)saveLastVersion:(SDVersionManager *)version;@end

SDVersionManager.m

#import "SDVersionManager.h"
#import "SDContextManager.h"#define kDataFileVersion @"UpdatedVersion"
#define kDocumentPath NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]@class SDVersionManagerDB;
@implementation SDVersionManager
/**单例模式使用 dispatch_once_t if不是线程安全的@return 实例对象*/
+ (instancetype)sharedInstance
{static SDVersionManager *_sharedInstance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{_sharedInstance = [[SDVersionManagerDB sharedInstance] loadLastVersion];if (_sharedInstance == nil) {_sharedInstance = [[SDVersionManager alloc] init];_sharedInstance.lastVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];}});return _sharedInstance;
}- (void)encodeWithCoder:(NSCoder *)aCoder {[aCoder encodeObject:_lastVersionCode forKey:NSStringFromSelector(@selector(lastVersionCode))];[aCoder encodeObject:_lastVersion forKey:NSStringFromSelector(@selector(lastVersion))];[aCoder encodeObject:_versionNotes forKey:NSStringFromSelector(@selector(versionNotes))];
}- (id)initWithCoder:(NSCoder *)aDecoder {if (self = [super init]) {_lastVersionCode = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(lastVersionCode))];_lastVersion = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(lastVersion))];_versionNotes = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(versionNotes))];}return self;
}/**检测版本更新,如果有新版本,提醒用户更新,提醒一次@param needUpdate 需要更新的回调@param failure 不需要更新*/
+ (void)checkAppVersion:(void (^) (void))needUpdatefailure:(void (^) (void))failure {NSURL *appstoreUrl = [NSURL URLWithString:[SDContextManager shareInstance].appstoreLookUrl];NSURLRequest *request = [NSURLRequest requestWithURL:appstoreUrl];NSString *currentVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];NSString *bundleCurrentVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];__weak typeof(currentVersion) weakCurrentVersion = currentVersion;__weak typeof(bundleCurrentVersion) weakBundleCurrentVersion = bundleCurrentVersion;[NSURLConnection sendAsynchronousRequest:requestqueue:[NSOperationQueue mainQueue]completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {if (!connectionError) {NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&connectionError];NSArray *results = [dic objectForKey:@"results"];if ([results count] > 0) {NSDictionary *resultValue = [results objectAtIndex:0];NSString *versionStr = [resultValue objectForKey:@"version"];NSString *version = [[resultValue objectForKey:@"version"] stringByReplacingOccurrencesOfString:@"." withString:@""];NSString *note = [resultValue objectForKey:@"releaseNotes"];NSString *curVersion = [weakCurrentVersion stringByReplacingOccurrencesOfString:@"." withString:@""];NSString *curBundleVersion = [weakBundleCurrentVersion stringByReplacingOccurrencesOfString:@"." withString:@""];[SDVersionManager sharedInstance].versionNotes = note;if ([curVersion integerValue] < [version integerValue]) {//当前版本比appstore上低NSString *alastVerstion = [SDVersionManager sharedInstance].lastVersion;if (alastVerstion && version && ([alastVerstion integerValue] < [version integerValue])) {[SDVersionManager sharedInstance].lastVersion = version;[SDVersionManager sharedInstance].lastVersionCode = versionStr;if (needUpdate) {needUpdate();}} else {if (failure) {failure();}}} else if ([curVersion integerValue] <= [version integerValue]) {//当前版本比appstore上相同[SDVersionManager sharedInstance].lastVersion = version;[SDVersionManager sharedInstance].lastVersionCode = versionStr;if (failure) {failure();}} else if ([curVersion integerValue] > [version integerValue]) {//当前版本比appstore上高[SDVersionManager sharedInstance].lastVersion = version;[SDVersionManager sharedInstance].lastVersionCode = versionStr;if (failure) {failure();}}[[SDVersionManagerDB sharedInstance] saveLastVersion:[SDVersionManager sharedInstance]];}} else {if (failure) {failure();}}}];
}@end#pragma mark - SDVersionManagerDB@implementation SDVersionManagerDB+ (instancetype)sharedInstance {static SDVersionManagerDB *_sharedInstance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{_sharedInstance = [[SDVersionManagerDB alloc] init];});return _sharedInstance;
}/**获取自定义对象UpdatedVersion实体,反序列化操作@return UpdatedVersion 实体*/
- (SDVersionManager *)loadLastVersion {NSString *dataFile = [NSString stringWithFormat:@"%@/%@", kDocumentPath, kDataFileVersion];@try{SDVersionManager *version = (SDVersionManager *)[NSKeyedUnarchiver unarchiveObjectWithFile:dataFile];if (version) {return version;}}@catch (NSException *e){}return nil;
}/**保存自定义对象序列化@param version UpdatedVersion实体@return 是否保存成功*/
- (BOOL)saveLastVersion:(SDVersionManager *)version {NSData *data = [NSKeyedArchiver archivedDataWithRootObject:version];NSString *dataFile = [NSString stringWithFormat:@"%@/%@", kDocumentPath, kDataFileVersion];return [data writeToFile:dataFile atomically:YES];
}@end

二、强制升级控制

强制更新控制,是将获取到当前版本号传给服务端,服务端判断当前的版本是否需要强制升级。

这块暂时就不写请求服务端的代码了。

三、小结

iOS开发-检查版本更新与强制更新控制。

在开发中经常遇到需要检查版本,检查版本及请求appstoreLookUrl查看版本号与当前的版本号进行比对,看是否需要更新。强制更新控制,是将获取到当前版本号传给服务端,服务端判断当前的版本是否需要强制升级。

学习记录,每天不停进步。

相关文章:

iOS开发-检查版本更新与强制更新控制

iOS开发-检查版本更新与强制更新控制。 在开发中经常遇到需要检查版本&#xff0c;检查版本及请求appstoreLookUrl查看版本号与当前的版本号进行比对&#xff0c;看是否需要更新。强制更新控制&#xff0c;是将获取到当前版本号传给服务端&#xff0c;服务端判断当前的版本是否…...

自动化运维工具——Ansible

自动化运维工具——Ansible 一、Ansible概述二、ansible 环境安装部署1.管理端安装 ansible2.ansible 目录结构3.配置主机清单4.配置密钥对验证 三、ansible 命令行模块1.command 模块2.shell 模块3.cron 模块4.user 模块5.group 模块6.copy 模块7.file 模块8.hostname 模块9&a…...

W2NER详解

论文&#xff1a;https://arxiv.org/pdf/2112.10070.pdf 代码&#xff1a;https://github.com/ljynlp/W2NER 文章目录 W2NER介绍模型架构解码 源码介绍数据输入格式模型代码 参考资料 W2NER 介绍 W2NER模型&#xff0c;将NER任务转化预测word-word&#xff08;备注&#xff…...

ElementUI tabs标签页样式改造美化

今天针对ElementUI的Tabs标签页进行了样式修改&#xff0c;更改为如下图所属的样子。 在线运行地址&#xff1a;JSRUN项目-ElementUI tabs标签页样式改造 大家如果有需要可以拿来修改使用&#xff0c;下面我也简单的贴上代码&#xff0c;代码没有注释&#xff0c;很抱歉&#x…...

出海周报|Temu在美状告shein、ChatGPT安卓版上线、小红书回应闪退

工程机械产业“出海”成绩喜人&#xff0c;山东相关企业全国最多Temu在美状告shein&#xff0c;跨境电商战事升级TikTok将在美国推出电子商务计划&#xff0c;售卖中国商品高德即将上线国际图服务&#xff0c;初期即可覆盖全球超200个国家和地区ChatGPT安卓版正式上线&#xff…...

2023年7月26日 单例模式

单例模式 饿汉模式 package com.wz.cinema.platform.server.util;public class DataManager {/*** 单例模式&#xff1a;整个类在运行中只会有一个实例* 既然是在运行中只有一个实例&#xff0c;那么就必须* 考虑多线程环境** 单例模式分为懒汉模式和饿汉模式* 饿汉模式本身就是…...

[ 容器 ] Docker 安全及日志管理

目录 Docker 容器与虚拟机的区别Docker 存在的安全问题Docker 架构缺陷与安全机制Docker 安全基线标准容器相关的常用安全配置方法限制流量流向镜像安全避免Docker 容器中信息泄露DockerClient 端与 DockerDaemon 的通信安全 容器的安全性问题的根源在于容器和宿主机共享内核。…...

游游的排列构造

示例1 输入 5 2 输出 3 1 5 2 4 示例2 输入 5 3 输出 2 1 4 3 5 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N1e55; int n,k; int main(){scanf("%d%d",&n,&k);int xn-k1;int yn-k;int f1;for(int i1;i&l…...

拯救者Y9000K无线Wi-Fi有时不稳定?该如何解决?

由于不同品牌路由器的性能差异&#xff0c;无法完美兼容最新的无线网卡技术&#xff0c;在连接网络时&#xff08;特别是网络负载较大的情况下&#xff09;&#xff0c;可能会出现Wi-Fi信号断开、无法网络无法访问、延迟突然变大的情况&#xff1b;可尝试下面方法进行调整。 1…...

【业务功能篇59】Springboot + Spring Security 权限管理 【下篇】

UserDetails接口定义了以下方法&#xff1a; getAuthorities(): 返回用户被授予的权限集合。这个方法返回的是一个集合类型&#xff0c;其中每个元素都是一个GrantedAuthority对象&#xff0c;表示用户被授予的权限。getPassword(): 返回用户的密码。这个方法返回的是一个字符…...

性能优化 - 前端性能监控和性能指标计算方式

性能优化 - 前端性能监控和性能指标计算方式 前言一. 性能指标介绍1.1 单一指标介绍1.2 指标计算① Redirect(重定向耗时)② AppCache(应用程序缓存的DNS解析)③ DNS(DNS解析耗时)④ TCP(TCP连接耗时)⑤ TTFB(请求响应耗时)⑥ Trans(内容传输耗时)⑦ DOM(DOM解析耗时) 1.3 FP(f…...

git stash clear清空本地暂存代码

git stash clear清空本地暂存代码 git stash 或者 git stash list 查看本地暂存的代码。 清除本地暂存的代码修改&#xff1a; git stash clear git回退代码仓库版本_git回退到之前的版本会影响本地代码嘛_zhangphil的博客-CSDN博客git回退代码版本_git回退到之前的版本会影…...

消防应急照明设置要求在炼钢车间电气室的应用

摘 要:文章以GB51309—2018《消防应急照明和疏散指示系统技术标准》为设计依据&#xff0c;结合某炼钢车间转炉项目的设计过程&#xff0c;在炼钢车间电气室的疏散照明和备用照明的设计思路、原则和方法等方面进行阐述。通过选择合理的消防应急疏散照明控制系统及灯具供配电方案…...

element 表单验证 深层验证绑定

直接上代码 :prop 和prop 都可以&#xff0c;vue2和vue3或者是element、elementplus都可以用 <template><div class"page page-table"><section class"page-query-form"><breadcrumb :hasLine"false" /></section&g…...

brew 换镜像网站

在国内,使用brew极慢. 因为它需要访问国外的一些服务器. 解决方法是使用国内的镜像站. 如果是首次安装: curl https://raw.githubusercontent.com/Homebrew/install/master/install.sh > install-brew.sh 然后,在下载的文件中, 修改BREW_REPO为: BREW_REPO"https…...

WIZnet W5500-EVB-Pico 静态IP配置教程(二)

W5500是一款高性价比的 以太网芯片&#xff0c;其全球独一无二的全硬件TCP、IP协议栈专利技术&#xff0c;解决了嵌入式以太网的接入问题&#xff0c;简单易用&#xff0c;安全稳定&#xff0c;是物联网设备的首选解决方案。WIZnet提供完善的配套资料以及实时周到的技术支持服务…...

R语言无法调用stats.dll的问题解决方案[补充]

写在前面 在去年10月份&#xff0c;出过一起关于R语言无法调用stats.dll的问题解决方案,今天&#xff08;你看到后是昨天&#xff09;不知道为什么&#xff0c;安装包&#xff0c;一直安装不了&#xff0c;真的是炸裂了。后面再次把R与Rstuido升级。说实话&#xff0c;我是真不…...

无线蓝牙耳机有什么推荐?怎么选择适合自己的耳机?七款蓝牙耳机分享

随着信息技术的不断发展&#xff0c;蓝牙耳机的不断发展也是必然的&#xff0c;可以说蓝牙耳机在大部分人们的生活中是不可缺少的一部分。那么我们该怎么去挑选出适合我们自己的需求的“蓝”朋友呢&#xff1f; 第一款&#xff1a;南卡小音舱lite2蓝牙耳机 推荐指数&#xff…...

【数据分析专栏之Python篇】四、pandas介绍

前言 在上一篇中我们安装和使用了Numpy。本期我们来学习使用 核心数据分析支持库 Pandas。 一、pandas概述 1.1 pandas 简介 Pandas 是 Python 的 核心数据分析支持库&#xff0c;提供了快速、灵活、明确的数据结构&#xff0c;旨在简单、直观地处理关系型、标记型数据。 …...

《算法竞赛·快冲300题》每日一题:“最小生成树”

《算法竞赛快冲300题》将于2024年出版&#xff0c;是《算法竞赛》的辅助练习册。 所有题目放在自建的OJ New Online Judge。 用C/C、Java、Python三种语言给出代码&#xff0c;以中低档题为主&#xff0c;适合入门、进阶。 文章目录 题目描述题解C代码Java代码Python代码 “ 最…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...