iOS简单实现版本更新检测

简介:
//
//  HYBVersionManager.h
//
//  Created by 黄仪标 on 15/1/27.
//

#import <Foundation/Foundation.h>

// 应用已经发布到APP Store后才会在Itunes上有应用的链接
// 所以版本检测必须是已经发布过才能做
// 在真正实现功能时,需要替换成真正的链接
// @requared
#define kAppStoreLink  @""
#define kItunsLink @""

/*!
 * 版本管理器
 */
@interface HYBVersionManager : NSObject

/*!
 * @brief 单例方法
 */
+ (HYBVersionManager *)sharedVersionManager;

/*
 * 调用此方法来执行版本检测
 * @param type
 */
- (void)checkVersion:(int)type;

@end


//
//  HYBVersionManager.m
//
//  Created by 黄仪标 on 15/1/27.
//

#import "HYBVersionManager.h"
#import "UIAlertView+Blocks.h"

#define kRequestTimeOut 60.0

@interface HYBVersionManager () {
  int         _type;
  UIAlertView *_alertView;
}

@end

@implementation HYBVersionManager

/*!
 * @brief 单例方法
 */
+ (HYBVersionManager *)sharedVersionManager {
  static HYBVersionManager *sharedObject = nil;
  static dispatch_once_t onceToken;
  
  dispatch_once(&onceToken, ^{
    if (!sharedObject) {
      sharedObject = [[self alloc] init];
    }
  });
  
  return sharedObject;
}

- (instancetype)init {
  if (self = [super init]) {
    _type = 0; // 自动检测
  }
  return self;
}

- (void)checkVersion:(int)type {
  _type = type;
  
  [self checkAppStoreVersion];
}

- (void)checkAppStoreVersion {
  if ([NSThread isMainThread]) {
    [self performSelectorInBackground:@selector(checkAppStoreVersion) withObject:nil];
    return;
  }
  
  @autoreleasepool  {
    //prevent concurrent checks
    static BOOL checking = NO;
    
    if (checking) return;
    checking = YES;
    
    NSError *error = nil;
    NSURLResponse *response = nil;
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:kItunsLink]
                                             cachePolicy:NSURLRequestReturnCacheDataElseLoad
                                         timeoutInterval:kRequestTimeOut];
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    NSInteger statusCode = ((NSHTTPURLResponse *)response).statusCode;
    if (data && statusCode == 200) {
      error = nil;
      id json = nil;
      if ([NSJSONSerialization class]) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
        json = [dict[@"results"] lastObject];
      } else {
        json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
      }
      
      if (!error) {
        // 获取到appstore上最新的版本号
        NSString *latestVersion = [self valueForKey:@"version" inJSON:json];
        NSString *localVersion = [self appLocalVersion];
        [self check:latestVersion localVersion:localVersion];
      }
    }
    
    // finished
    checking = NO;
  }
}

- (void)check:(NSString *)latestVersion localVersion:(NSString *)localVersion {
  if ([latestVersion compare:localVersion] == NSOrderedDescending) { // 有新版本
    [self showPromptForUpdate];
  } else if ([latestVersion compare:localVersion options:NSNumericSearch] == NSOrderedSame) {// 已经是最新版本
    if (_type == 1) { // 手动
      [self showMessage];
    }
  }
}

- (void)showMessage {
  if (_alertView) {
    _alertView.hidden = YES;
    [_alertView removeFromSuperview];
    _alertView = nil;
  }
  
  UIAlertView *alert = [UIAlertView showWithTitle:@""
                                          message:@"当前版本已经是最新版本!"
                                         okButton:@"确定"
                                     cancelButton:nil];
  _alertView = alert;
}

- (void)showPromptForUpdate {
  [UIAlertView showWithTitle:nil
                     message:@"有新版本发布了,亲,快去更新吧!"
           cancelButtonTitle:@"暂不更新"
           otherButtonTitles:@[@"立即更新"] tapBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {
                                 if (buttonIndex == 0) {
                                   
                                 } else {
                                   [[UIApplication sharedApplication] openURL:[NSURL URLWithString:kAppStoreLink]];
                                 }
                               }];
}

/*!
 * @brief 获取app本地的版本号
 */
- (NSString *)appLocalVersion {
  NSDictionary *info = [[NSBundle mainBundle] infoDictionary];
  NSString *version = [info objectForKey:@"CFBundleVersion"];
  
  return [version stringByTrimmingCharactersInSet:[NSCharacterSet letterCharacterSet]];
}

- (NSString *)valueForKey:(NSString *)key inJSON:(id)json {
  if ([json isKindOfClass:[NSString class]]) {
    //use legacy parser
    NSRange keyRange = [json rangeOfString:[NSString stringWithFormat:@"\"%@\"", key]];
    if (keyRange.location != NSNotFound) {
      NSInteger start = keyRange.location + keyRange.length;
      NSRange valueStart = [json rangeOfString:@":" options:(NSStringCompareOptions)0 range:NSMakeRange(start, [(NSString *)json length] - start)];
      if (valueStart.location != NSNotFound) {
        start = valueStart.location + 1;
        NSRange valueEnd = [json rangeOfString:@"," options:(NSStringCompareOptions)0 range:NSMakeRange(start, [(NSString *)json length] - start)];
        if (valueEnd.location != NSNotFound) {
          NSString *value = [json substringWithRange:NSMakeRange(start, valueEnd.location - start)];
          value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
          while ([value hasPrefix:@"\""] && ![value hasSuffix:@"\""]) {
            if (valueEnd.location == NSNotFound) {
              break;
            }
            NSInteger newStart = valueEnd.location + 1;
            valueEnd = [json rangeOfString:@"," options:(NSStringCompareOptions)0 range:NSMakeRange(newStart, [(NSString *)json length] - newStart)];
            value = [json substringWithRange:NSMakeRange(start, valueEnd.location - start)];
            value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
          }
          
          value = [value stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\""]];
          value = [value stringByReplacingOccurrencesOfString:@"\\\\" withString:@"\\"];
          value = [value stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"];
          value = [value stringByReplacingOccurrencesOfString:@"\\\"" withString:@"\""];
          value = [value stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"];
          value = [value stringByReplacingOccurrencesOfString:@"\\r" withString:@"\r"];
          value = [value stringByReplacingOccurrencesOfString:@"\\t" withString:@"\t"];
          value = [value stringByReplacingOccurrencesOfString:@"\\f" withString:@"\f"];
          value = [value stringByReplacingOccurrencesOfString:@"\\b" withString:@"\f"];
          
          while (YES) {
            NSRange unicode = [value rangeOfString:@"\\u"];
            if (unicode.location == NSNotFound || unicode.location + unicode.length == 0) {
              break;
            }
            
            uint32_t c = 0;
            NSString *hex = [value substringWithRange:NSMakeRange(unicode.location + 2, 4)];
            if (hex != nil) {
              NSScanner *scanner = [NSScanner scannerWithString:hex];
              [scanner scanHexInt:&c];
            }
            
            if (c <= 0xffff) {
              value = [value stringByReplacingCharactersInRange:NSMakeRange(unicode.location, 6) withString:[NSString stringWithFormat:@"%C", (unichar)c]];
            } else {
              //convert character to surrogate pair
              uint16_t x = (uint16_t)c;
              uint16_t u = (c >> 16) & ((1 << 5) - 1);
              uint16_t w = (uint16_t)u - 1;
              unichar high = 0xd800 | (w << 6) | x >> 10;
              unichar low = (uint16_t)(0xdc00 | (x & ((1 << 10) - 1)));
              
              value = [value stringByReplacingCharactersInRange:NSMakeRange(unicode.location, 6) withString:[NSString stringWithFormat:@"%C%C", high, low]];
            }
          }
          return value;
        }
      }
    }
  } else {
    return json[key];
  }
  return nil;
}

@end

之前使用了iLink库,可是后来出现了很多的问题,于是不得不去掉,自己写一个,完全自主控制了。

这里功能很简单,一种是自动检测,也就是在应用启动的时候调用,

另一种是手动检测,一般是放在设置中的检查版本更新时,手动检测。

目录
相关文章
|
测试技术 程序员 C++
iOS:项目中无用类检测和无用图片检测汇总
在涉及到项目大改版,或者涉及到某个功能模块大变更,就会涉及到图片废弃和文件废弃的情况。 但是这时候就会遗留下一个很大的问题,没有将废弃的、无用的文件类或资源删除干净。而这次需要对工程代码的无用资源和无用文件进行删除处理,感触颇多,故在此笔记。 首先,感觉很多人的代码习惯还是恶待提高。比如我发现一些人的代码操作习惯,从好到次,可以大略分以下情况
1130 0
iOS:项目中无用类检测和无用图片检测汇总
|
2月前
|
移动开发 开发工具 数据安全/隐私保护
iOS APP 版本更新升级教程:如何打包上架新的 APP 版本?
iOS APP 版本更新升级教程:如何打包上架新的 APP 版本?
iOS APP 版本更新升级教程:如何打包上架新的 APP 版本?
|
2月前
|
监控 API iOS开发
克魔助手 - iOS性能检测平台
众所周知,如今的用户变得越来越关心app的体验,开发者必须关注应用性能所带来的用户流失问题。目前危害较大的性能问题主要有:闪退、卡顿、发热、耗电快、网络劫持等,但是做过iOS开发的人都知道,在开发过程中我们没有一个很直观的工具可以实时的知道开发者写出来的代码会不会造成性能问题,虽然Xcode里提供了耗电量检测、内存泄漏检测等工具,但是这些工具使用效果并不理想(如Leak无法发现循环引用造成的内存泄漏)。所以这篇文章主要是介绍一款实时监控app各项性能指标的工具,包括CPU占用率、内存使用量、内存泄漏、FPS、卡顿检测,并且会分析造成这些性能问题的原因。
|
7月前
|
iOS开发
iOS UIDevice & 屏幕旋转检测
iOS UIDevice & 屏幕旋转检测
30 0
|
7月前
|
移动开发 开发工具 数据安全/隐私保护
iOS APP版本更新升级教程:如何打包上架新的APP版本?
本篇博客将介绍如何快速、简便地完成APP更新升级流程,让你的用户享受到更好的使用体验。使用常用开发工具打包,注意版本号的修改。进入APP页面点击“所有构建版本”选项,这里会显示上传成功的构建版本。输入更新说明,修改APP描述、关键词等,选择是否为新功能。如审核通过则恭喜你,否则根据反馈修改再重新上传提交审核。
|
9月前
|
存储 iOS开发
iOS主线程耗时检测方案
找出那个拖后腿的凶手
126 1
iOS主线程耗时检测方案
|
11月前
|
iOS开发
iOS 检测字符串中数字个数、特殊符号个数
iOS 检测字符串中数字个数、特殊符号个数
135 0
|
11月前
|
iOS开发
iOS 检测字符串中是否含有数字、特殊符号
iOS 检测字符串中是否含有数字、特殊符号
311 0
|
11月前
|
iOS开发
iOS 检测字符串中是否含有字母、大写字母、小写字母
iOS 检测字符串中是否含有字母、大写字母、小写字母
281 0
|
iOS开发
IOS版本更新代码——商店版本
IOS版本更新代码——商店版本
125 0