1

我正在为内部企业应用程序创建更新方法。我要创建的是一个可以快速放入应用程序的类,如果需要更新,它将与服务器检查。这就是我到目前为止所拥有的,它检查正确,但它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。我需要它是异步的,因为应用程序将检查的服务器位于我们的防火墙后面。因此,如果此人在防火墙之外,则应用程序需要在无法访问服务器时继续。我是朝着正确的方向前进,还是有更好的方法?

4

2 回答 2

3

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

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

于 2013-02-27T16:25:35.947 回答
3

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

注意:未经检查和未经测试的错误;然而,从这个例子中得到的教训是使用各种回调:

更新检查器类

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];
}];
于 2013-02-27T16:28:42.790 回答