【问题标题】:App Checking for updates应用程序检查更新
【发布时间】:2013-02-27 16:06:15
【问题描述】:

我正在为内部企业应用程序创建更新方法。我要创建的是一个可以快速放入应用程序的类,如果需要更新,它将与服务器检查。这是我目前所拥有的,它检查正确,但在完成方法之前返回NO

在我的 checkUpdate.h 中

@interface checkForUpdate : NSObject

+ (BOOL)updateCheck;


@end

在我的 checkUpdate.m 中

#import "checkForUpdate.h"

@implementation checkForUpdate

BOOL needsUpdate
NSDictionary *versionDict;


#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)


+ (BOOL)updateCheck {

    NSString *urlStringVersion = [[NSString alloc] initWithFormat:@"http://URL/app_info?app=app"];
    NSURL *urlVersion = [NSURL URLWithString:urlStringVersion];

    dispatch_async(kBgQueue, ^{
        NSData* data =[NSData dataWithContentsOfURL:urlVersion];

        if (data){
            NSError* error;
            NSArray* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
            if (json != nil && [json count] != 0) {
                versionDict = [json objectAtIndex:0];

                CGFloat serverVersion = [[versionDict valueForKey:@"version"]floatValue];
                CGFloat appVersion = [[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey] floatValue];
                NSLog(@"Server Version %f",serverVersion);
                NSLog(@"App Version %f",appVersion);

                if ([versionDict count] != 0){
                    if (serverVersion > appVersion){
                        [[UIApplication sharedApplication] setApplicationIconBadgeNumber:1];
                        needsUpdate = YES;
                    }else{
                        [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
                        needsUpdate = NO;
                    }
                }

            }
        }

    });

    return needsUpdate;

}


@end

我这样称呼它

NSLog(@"Needs Update %@",[checkForUpdate checkForUpdateWithResponse] ? @"Yes":@"No");

这是我的日志

 Needs Update No
 Server Version 2.000000
 App Version 1.000000

我不确定为什么它在检查之前就返回 NO。我需要它是异步的,因为应用程序将检查的服务器位于我们的防火墙后面。因此,如果此人在防火墙之外,则应用程序需要在无法访问服务器时继续。我的方向是正确的,还是有更好的方法?

【问题讨论】:

    标签: ios objective-c methods


    【解决方案1】:

    您正在异步检查更新,但由于您的方法设计而期望立即响应。您可以将您的方法重新设计为如下示例,以便在操作完成时通知处理程序:

    注意:未经检查和未经测试的错误;但是,从示例中吸取的教训是使用各种回调:

    UpdateChecker 类

    typedef void (^onComplete)(BOOL requiresUpdate);
    
    @interface UpdateChecker : NSObject
    -(void)checkForUpdates:(onComplete)completionHandler;
    @end
    
    @implementation UpdateChecker
    -(void)checkForUpdates:(onComplete)completionHandler
    {
        NSString *urlStringVersion = [[NSString alloc] initWithFormat:@"http://URL/app_info?app=app"];
        NSURL *urlVersion = [NSURL URLWithString:urlStringVersion];
        dispatch_block_t executionBlock = 
        ^{
             /*
                 Your update checking script here
                 (Use the same logic you are currently using to retrieve the data using the url)
              */
             NSData* data = [NSData dataWithContentsOfURL:urlVersion];
             BOOL requiresUpdate = NO; 
             if (data)
             { 
                 ...
                 ...
                 ...
                 requiresUpdate = ...; //<-whatever your outcome
             }
    
             //Then when completed, notify the handler (this is our callback)
             //Note: I typically call the handler on the main thread, but is not required.  
             //Suit to taste.
             dispatch_async(dispatch_get_main_queue(),
             ^{
                 if (completionHandler!=NULL)
                     completionHandler(requiresUpdate);
             });
        };
        dispatch_async(kBgQueue, executionBlock);
    }
    @end
    

    这就是您使用 UpdateChecker 检查整个应用程序更新时的样子

    UpdateChecker *checker = [UpdateChecker alloc] init];
    [checker checkForUpdates:^(BOOL requiresUpdate)
    {
         if (requiresUpdate)
         {
            //Do something if your app requires update
            [[UIApplication sharedApplication] setApplicationIconBadgeNumber:1];
         }
         else         
            [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
    }];
    

    【讨论】:

    • 所以这对我来说是一个全新的事物,我只是想弄清楚这个问题。你能告诉我更多我将如何实现它吗?
    • 稍微修改了答案以使您步入正轨。请注意我添加的关于使用相同逻辑的评论。把你所有的逻辑放在那个地方。我已经包含了你的代码的一个小sn-p,这样你就可以得到更好的结果。
    • 在我的第二个示例中,您提供的代码块(大括号之间的内容)将在您的更新检查完成时被调用。这被称为回调,意思是,在您检查完我的更新后通知我,以便我可以做点什么
    • 非常感谢。我对使用调度很陌生。您知道有关使用调度的任何好的教程或书籍吗?
    【解决方案2】:

    由于dispatch_async 是非阻塞的,因此您的方法会在更新信息返回之前返回(执行调度并继续)。由于needsUpdate 默认为NO,这就是您将看到的。您可以在日志时间中看到这一点 - “Needs Update No”出现在服务器和应用程序版本之前。

    您需要某种回调(例如委托方法或第二个dispatch_async)以确保获得正确的结果,否则您需要阻止。我建议查看NSURLConnectionsendAsynchronousRequest:queue:completionHandler: - 它会在完成时执行完成处理程序,您可以在其中拥有处理更新所需的任何代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-11
      • 2013-01-21
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多