`
ydbc
  • 浏览: 741887 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

ios开发 升级App

 
阅读更多
//
// CWLSynthesizeSingleton.h
// CocoaWithLove
//
// Created by Matt Gallagher on 2011/08/23.
// Copyright (c) 2011 Matt Gallagher. All rights reserved.
//
// Permission is given to use this source code file, free of charge, in any
// project, commercial or otherwise, entirely at your risk, with the condition
// that any redistribution (in part or whole) of source code must retain
// this copyright and permission notice. Attribution in compiled projects is
// appreciated but not required.
//

#import <objc/runtime.h>

#define CWL_DECLARE_SINGLETON_FOR_CLASS_WITH_ACCESSOR(classname, accessorMethodName) \
+ (classname *)accessorMethodName;

#if __has_feature(objc_arc)
#define CWL_SYNTHESIZE_SINGLETON_RETAIN_METHODS
#else
#define CWL_SYNTHESIZE_SINGLETON_RETAIN_METHODS \
- (id)retain \
{ \
return self; \
} \
\
- (NSUInteger)retainCount \
{ \
return NSUIntegerMax; \
} \
\
- (oneway void)release \
{ \
} \
\
- (id)autorelease \
{ \
return self; \
}
#endif

#define CWL_SYNTHESIZE_SINGLETON_FOR_CLASS_WITH_ACCESSOR(classname, accessorMethodName) \
\
static classname *accessorMethodName##Instance = nil; \
\
+ (classname *)accessorMethodName \
{ \
@synchronized(self) \
{ \
if (accessorMethodName##Instance == nil) \
{ \
accessorMethodName##Instance = [super allocWithZone:NULL]; \
accessorMethodName##Instance = [accessorMethodName##Instance init]; \
method_exchangeImplementations(\
class_getClassMethod([accessorMethodName##Instance class], @selector(accessorMethodName)),\
class_getClassMethod([accessorMethodName##Instance class], @selector(cwl_lockless_##accessorMethodName)));\
method_exchangeImplementations(\
class_getInstanceMethod([accessorMethodName##Instance class], @selector(init)),\
class_getInstanceMethod([accessorMethodName##Instance class], @selector(cwl_onlyInitOnce)));\
} \
} \
\
return accessorMethodName##Instance; \
} \
\
+ (classname *)cwl_lockless_##accessorMethodName \
{ \
return accessorMethodName##Instance; \
} \
\
+ (id)allocWithZone:(NSZone *)zone \
{ \
return [self accessorMethodName]; \
} \
\
- (id)copyWithZone:(NSZone *)zone \
{ \
return self; \
} \
- (id)cwl_onlyInitOnce \
{ \
return self;\
} \
\
CWL_SYNTHESIZE_SINGLETON_RETAIN_METHODS

#define CWL_DECLARE_SINGLETON_FOR_CLASS(classname) CWL_DECLARE_SINGLETON_FOR_CLASS_WITH_ACCESSOR(classname, shared##classname)

#define CWL_SYNTHESIZE_SINGLETON_FOR_CLASS(classname) CWL_SYNTHESIZE_SINGLETON_FOR_CLASS_WITH_ACCESSOR(classname, shared##classname)










//
// PSUpdateApp.h
// PSUpdateApp
//
// Created by iBo on 18/02/13.
// Copyright (c) 2013 D-Still. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "CWLSynthesizeSingleton.h"

typedef void(^PSUpdateAppCompletionBLock)(NSError *error, BOOL success, id JSON);

typedef enum {
DefaultStrategy = 0,
ForceStrategy,
RemindStrategy
} UpdateStrategy;

@interface PSUpdateApp : NSObject

CWL_DECLARE_SINGLETON_FOR_CLASS(PSUpdateApp)

@property (nonatomic) NSString *appID, *appStoreLocation, *appName, *route, *updatePageUrl;
@property (nonatomic) UpdateStrategy strategy;
@property (nonatomic) int daysUntilPrompt;
@property (nonatomic) NSDate *remindDate;

+ (id) startWithRoute:(NSString *)route;
+ (id) startWithAppID:(NSString *)appId;
+ (id) startWithAppID:(NSString *)appId store:(NSString *)store;

- (void) detectAppVersion:(PSUpdateAppCompletionBLock)completionBlock;
- (void) setURLAdHoc:(NSString *)url;

@end






//
// PSUpdateApp.m
// PSUpdateApp
//
// Created by iBo on 18/02/13.
// Copyright (c) 2013 D-Still. All rights reserved.
//

#ifndef PSUdateAppLocalizedStrings
#define PSUdateAppLocalizedStrings(key) \
NSLocalizedStringFromTable(key, @"PSUdateApp", nil)
#endif

#import "PSUpdateApp.h"
#import <AFNetworking/AFNetworking.h>

#define APPLE_URL @"http://itunes.apple.com/lookup?"

#define kCurrentAppVersion [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]

@interface PSUpdateApp () <UIAlertViewDelegate> {
NSString *_newVersion;
}
@end

@implementation PSUpdateApp

CWL_SYNTHESIZE_SINGLETON_FOR_CLASS(PSUpdateApp)

+ (id) startWithRoute:(NSString *)route
{
return [[self alloc] initWithAppID:nil store:nil route:route];
}

+ (id) startWithAppID:(NSString *)appId store:(NSString *)store
{
return [[self alloc] initWithAppID:appId store:store route:nil];
}

+ (id) startWithAppID:(NSString *)appId
{
return [[self alloc] initWithAppID:appId store:nil route:nil];
}

- (id) initWithAppID:(NSString *)appId store:(NSString *)store route:(NSString *)route
{
self = [super init];

if ( self ) {
[self setAppName:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]];
[self setStrategy:DefaultStrategy];
[self setAppID:appId];
[self setAppStoreLocation: store ? store : [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode]];
[self setDaysUntilPrompt:2];
[self setRoute:route];
}

return self;
}

- (void) detectAppVersion:(PSUpdateAppCompletionBLock)completionBlock
{
if ( _strategy == RemindStrategy && [self remindDate] != nil && ![self checkConsecutiveDays] )
return;

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:[self setJsonURL]]];
[request setHTTPMethod:@"GET"];

AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
if ( [self isNewVersion:JSON] ) {
if ( completionBlock && ![self isSkipVersion] ) {
completionBlock(nil, YES, JSON);
} else if ( ![self isSkipVersion] ) {
[self showAlert];
} else {
if ( completionBlock )
completionBlock(nil, NO, JSON);
}
} else {
if ( completionBlock )
completionBlock(nil, NO, JSON);
}
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
if ( completionBlock && ![self isSkipVersion] )
completionBlock(error, NO, nil);
}];
[operation start];
}

- (NSString *) setJsonURL
{
return self.route ? self.route : [NSString stringWithFormat:@"%@id=%@&country=%@", APPLE_URL, self.appID, self.appStoreLocation];
}

- (void) setURLAdHoc:(NSString *)url
{
[self setRoute:[NSString stringWithFormat:url, self.appStoreLocation]];
}

#pragma mark - Check version

- (BOOL) isNewVersion:(NSDictionary *)dictionary
{
if ( [[dictionary objectForKey:@"results"] count] > 0 ) {
_newVersion = [[[dictionary objectForKey:@"results"] objectAtIndex:0] objectForKey:@"version"];
[self setUpdatePageUrl:[[[dictionary objectForKey:@"results"] objectAtIndex:0] objectForKey:@"trackViewUrl"]];

if ([[[dictionary objectForKey:@"results"] objectAtIndex:0] objectForKey:@"type"]) {
[self setStrategy: [[[[dictionary objectForKey:@"results"] objectAtIndex:0] objectForKey:@"type"] isEqualToString:@"mandatory"] ? ForceStrategy : DefaultStrategy];
}

return [kCurrentAppVersion compare:_newVersion options:NSNumericSearch] == NSOrderedAscending;
}

return NO;
}

- (BOOL) isSkipVersion
{
return [[[NSUserDefaults standardUserDefaults] objectForKey:@"skipVersion"] isEqualToString:_newVersion];
}

#pragma mark - remindDate getter / setter

- (NSDate *) remindDate
{
return [[NSUserDefaults standardUserDefaults] objectForKey:@"remindDate"];
}

- (void) setRemindDate:(NSDate *)remindDate
{
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"remindDate"];
[[NSUserDefaults standardUserDefaults] synchronize];
}

#pragma mark - Show alert

- (void) showAlert
{
switch ( self.strategy ) {
case DefaultStrategy:
default:
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:PSUdateAppLocalizedStrings(@"alert.success.title")
message:[NSString stringWithFormat:PSUdateAppLocalizedStrings(@"alert.success.default.text"), self.appName, _newVersion]
delegate:self
cancelButtonTitle:PSUdateAppLocalizedStrings(@"alert.button.skip")
otherButtonTitles:PSUdateAppLocalizedStrings(@"alert.button.update"), nil];
[alertView show];
}
break;

case ForceStrategy:
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:PSUdateAppLocalizedStrings(@"alert.success.title")
message:[NSString stringWithFormat:PSUdateAppLocalizedStrings(@"alert.success.force.text"), self.appName, _newVersion]
delegate:self
cancelButtonTitle:PSUdateAppLocalizedStrings(@"alert.button.update")
otherButtonTitles:nil, nil];
[alertView show];
}
break;

case RemindStrategy:
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:PSUdateAppLocalizedStrings(@"alert.success.title")
message:[NSString stringWithFormat:PSUdateAppLocalizedStrings(@"alert.success.remindme.text"), _appName, _newVersion]
delegate:self
cancelButtonTitle:PSUdateAppLocalizedStrings(@"alert.button.skip")
otherButtonTitles:PSUdateAppLocalizedStrings(@"alert.button.update"), PSUdateAppLocalizedStrings(@"alert.button.remindme"), nil];
[alertView show];
}
break;
}
}


#pragma mark - UIAlertViewDelegate Methods

- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch ( self.strategy ) {
case DefaultStrategy:
default:
{
if ( buttonIndex == 0 ) {
[[NSUserDefaults standardUserDefaults] setObject:_newVersion forKey:@"skipVersion"];
[[NSUserDefaults standardUserDefaults] synchronize];
} else {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:self.updatePageUrl]];
}
}

break;

case ForceStrategy:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:self.updatePageUrl]];
break;

case RemindStrategy:
{
if ( buttonIndex == 0 ) {
[[NSUserDefaults standardUserDefaults] setObject:_newVersion forKey:@"skipVersion"];
[[NSUserDefaults standardUserDefaults] synchronize];
} else if ( buttonIndex == 1 ) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:self.updatePageUrl]];
} else {
[self setRemindDate:[NSDate date]];
}
}

break;
}
}

#pragma mark - Check if have passed

- (BOOL) checkConsecutiveDays
{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDate *today = [NSDate date];

NSDate *dateToRound = [[self remindDate] earlierDate:today];
NSDateComponents * dateComponents = [gregorian components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
fromDate:dateToRound];

NSDate *roundedDate = [gregorian dateFromComponents:dateComponents];
NSDate *otherDate = (dateToRound == [self remindDate]) ? today : [self remindDate] ;
NSInteger diff = abs([roundedDate timeIntervalSinceDate:otherDate]);
NSInteger daysDifference = floor(diff/(24 * 60 * 60));

return daysDifference >= _daysUntilPrompt;
}

@end


分享到:
评论

相关推荐

    苹果iOS app开发之更新升级app的办法.zip

    - `iOS开发 判断当前APP版本和升级.url`:这个链接可能指向一个教程,详细解释如何在代码中判断和处理版本更新。 - `苹果app不能出现 当前版本 字样.txt`:文件可能列出苹果关于此规定的详细信息。 - `iOS开发 ...

    iOS开发之一句代码检测App版本的更新

    在iOS应用开发中,定期检测并提示用户更新App版本是保持应用活跃度和用户...总的来说,通过一句代码实现的版本检测和更新跳转是iOS开发中的一个实用技巧,它能帮助开发者有效地提醒用户升级应用,保持应用的最新状态。

    IOS开发官方教程(中文)

    开发 iOS 应用程序,您需要: Mac 电脑,运行 OS X 10.8 (Mountain Lion) 或更高版本 Xcode iOS SDK Xcode 是 Apple 的集成开发环境 (IDE)。Xcode 包括源代码编辑器、图形用户界面编辑器和许多其他功 能。iOS SDK 扩展...

    swift-SwiftWeather采用Swift2开发的iOS天气App

    SwiftWeather是一款基于Swift...通过分析SwiftWeather项目,我们可以深入学习Swift编程语言、iOS开发最佳实践以及如何构建一个完整的iOS应用。无论是对于初学者还是经验丰富的开发者,这个项目都提供了丰富的学习资源。

    java ios自动升级服务

    Java和iOS自动升级服务是移动应用开发中一个重要的功能,它允许用户无痛地更新到最新版本的应用,提高用户体验并确保他们始终运行安全且优化的软件。以下是对这个主题的详细解析: 首先,我们要理解自动升级服务的...

    ios应用升级 更新提示

    在iOS开发中,开发者可能会创建这样一个组件来跟踪当前应用的版本号,比较它与App Store中的最新版本,从而决定是否显示更新提示。此外,这个模块还可能负责处理更新过程,比如下载更新包、暂停或恢复下载、处理错误...

    uni-app项目基于IOS平台的开发及配置.docx

    uni-app 项目基于 IOS 平台的开发及配置 一、 开发环境 在uni-app项目基于IOS平台的开发及配置中,首先需要安装Xcode 12.1 及以上版本,并下载HBuilderX的IOS版本,下载地址为...

    iOS 16 真机开发包 正式版

    iOS 16 真机开发包 正式版. 使用方法: 将下载好的调试包解压,快捷键command+shift+g前往文件夹: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport 把解压后的文件放入到该...

    ios开发基础教程源代码 完整版

    在iOS开发领域,掌握基础知识是至关重要的,尤其是对于初学者来说。这个“iOS开发基础教程源代码 完整版”提供了宝贵的实践资源,帮助开发者深入理解iOS应用开发的核心概念。这个压缩包包含的"Begin_iOS_5_projects_...

    IOS 7 app essential

    综上所述,文档中提到的每一个知识点都是iOS开发过程中不可或缺的部分。掌握这些知识对iOS开发新手来说是非常重要的。开发者在阅读完这些内容之后,应当能够更好地理解iOS 7的应用开发流程,以及如何使用Xcode和其他...

    ios13.3真机开发包

    在iOS应用开发过程中,开发者时常会遇到“Could not find Developer Disk Image”这样的错误,这通常是由于Xcode缺少对应iOS版本的SDK...因此,这个“ios13.3真机开发包”是iOS开发过程中不可或缺的工具之一。

    ios 10.2开发包

    **iOS 10.2 开发包详解** iOS 10.2 是苹果公司为iPhone、iPad和iPod touch推出的操作系统版本,它在iOS 10的基础上进行了诸多更新和优化,旨在提供更好的用户体验和增强设备的功能性。这个开发包包含了针对开发者...

    Windows下Ios开发环境搭建及基本开发操作.pdf

    Windows 下 iOS 开发环境搭建及基本开发操作 Windows 下 iOS 开发环境搭建是 iOS 开发的必备步骤,而基本开发操作是新手必须掌握的技能。本文将指导读者如何在 Windows 下搭建 iOS 开发环境,并学习基本的开发操作...

    iOS7 App Development Essentials

    iOS7应用开发基础是针对苹果公司的移动操作系统iOS 7版本和集成开发环境Xcode 5的软件...通过这本书,开发者可以构建在iOS 7上运行的高质量、适应性强的应用程序,并为在后续iOS版本上进行升级和维护打下坚实的基础。

    ios13.4真机开发包

    在iOS应用开发过程中,开发者时常会遇到“Could not find Developer Disk Image”这样的错误,这个问题通常是由于Xcode中的SDK(Software Development Kit)版本不匹配引起的。当用户的iOS设备系统升级到新版本,...

    ios升级新控件3.1.1改造指南1.0.docx

    iOS 支付控件 SDK 升级新控件 3.1.1 改造指南是为了帮助已经接入过 iOS 版银联支付控件 SDK 的商户升级到新版本。下面是该升级指南的重要知识点总结: 一、SDK 版本升级 * 根据商户选择的 SDK 版本,将 sdk/inc ...

    iOS 16.1 真机开发包 正式版

    注意:升级到iOS 16后需打开开发者模式否则Xcode会报错“Failed to prepare device for development”,一直转圈不能调试。入口为:设置-隐私与安全性 安全性-开发者模式打开,打开后会重启手机,之后再调试就可以了...

    马上着手开发 iOS 应用程序

    例如,可以通过App Store的帮助文章、指南、API参考、QuickHelp以及示例代码来深入理解iOS开发的各个方面。开发者也可以通过教程来学习如何使用Xcode进行用户界面设计、游戏开发、数据管理以及多媒体处理。 总的来...

    VMWare 上搭建iOS开发环境SOP

    在VMware上搭建iOS开发环境的总体方案是使用64位Windows 7作为宿主机,通过VMware 9安装Mac OS X Mavericks虚拟机。这个环境将用于安装和运行Xcode,从而进行iOS应用的开发和打包发布。Swift编程语言的使用也包含在...

Global site tag (gtag.js) - Google Analytics