(iOS)脱机同步数据库 - 服务器

时间:2013-03-12 13:11:23

标签: ios objective-c sqlite synchronization

尝试实现一个应用程序,该应用程序在连接到Internet时将存储在本地数据库中的脱机数据发送到Web服务器。我使用下面显示的代码。到目前为止,我测试它工作正常,不确定它将适用于大量的记录。我想知道是否对此代码进行任何调整可能会提高性能???

注意

  • 我知道这对于离线同步目的而言是最差的代码,所以尝试一下 更好地调整它。
  • 从app到服务器的单向同步。

    -(void)FormatAnswersInJSON {
    
      DMInternetReachability *checkInternet = [[DMInternetReachability alloc] init];
      if ([checkInternet isInternetReachable]) {
         if ([checkInternet isHostReachable:@"www.apple.com"]) {//Change to domain
            responseArray = [[NSMutableArray alloc] init];
    
            dispatch_async(backgroundQueue, ^(void) {
    
                NSArray *auditIDArray = [[NSArray alloc] initWithArray: [self getUnuploadedIDs]];
                for (int temp = 0; temp < [auditIDArray count]; temp ++) {
    
                    // Code to post JSON to server
    
                    NSURLResponse *response;
                    NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
                    if (!error) {
                        NSString *responseID = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
                        if ([responseID isEqualToString:@"ERROR"]) {
                            //Error uploading records
                        } else {
                           [responseArray addObject:responseID];
                        }
                    } else {
                       //Error
                       return;
                    }
                }
                dispatch_async( backgroundQueue, ^{
    
                    /* Based on return code update local DB */
                    for (int temp = 0; temp < [responseArray count]; temp ++) {
                       [self updateRecordsForID:[auditIDArray objectAtIndex:temp] withID:[responseArray objectAtIndex:temp]];
                    }
                });
            });
         }
      }
    }
    
    - (void)upload { //Called when internet connection available
    
        if(backgroundQueue){
            dispatch_suspend(backgroundQueue);
            dispatch_release(backgroundQueue);
            backgroundQueue = nil;
        }
        backgroundQueue = dispatch_queue_create("com.XXXX.TestApp.bgqueue", NULL);
        dispatch_async(backgroundQueue, ^(void) {
            [self FormatAnswersInJSON];
        });    
    }
    

2 个答案:

答案 0 :(得分:1)

如果这段代码放在我面前,我的方法是:

  • 查看用例并定义“大量记录”:是否会定期更新50条记录?或者是1s和2s?我的用户是否有wifi连接或是通过付费网络?等等。
  • 如果可能的话,在野外进行测试。如果我的用户群足够小,请收集实际数据并指导我做出决定,或者仅将功能发布到用户/ beta测试的子集并进行衡量。
  • 如果数据告诉您,则优化此代码以提高效率。

我的优化途径是进行群组处理。粗略的算法类似于:

for records in groups of X
  collect
  post to server {
    on return:
      gather records that updated successfully
      update locally
  }

这假设您可以修改服务器代码。你可以做10,20,50等组,所有这些都取决于发送的数据类型和大小。

组算法意味着更多的预处理客户端,但具有减少HTTP请求的能力。如果您只获得少量更新,则YAGNI和预成熟优化。

请勿让此决定阻止您发货!

答案 1 :(得分:0)

您的代码有几个问题。一种惯例是在测试error参数之前始终检查返回值。可能会设置error参数 - 即使方法成功。

NSURLConnection用于快速示例或测试以外的任何其他内容时,您还应始终使用异步样式来处理委托方法。由于正确使用NSURLConnection 可能会变得很麻烦且容易出错,我建议使用第三方框架封装NSURLConnection对象和所有连接相关的状态信息作为子类NSOperation。您可以在Apple示例中找到一个示例实现:QHTTPOperation。另一个合适的第三方框架是AFNetworking(在GitHub上)。

当您使用带有委托或第三方子类的异步样式时,您可以取消连接,检索详细错误或进度信息,执行身份验证等等 - 使用同步API无法实现这一点。

我认为,一旦你完成了这个并且你的方法正常工作,你可以测试性能是否可以接受。但除非你有大量数据 - 比如&gt; 2 MByte - 我不会太担心。

如果您的数据变得非常大,请说> 10 MByte,您需要考虑改进您的方法。例如,您可以将POST数据作为文件流而不是NSData对象提供(请参阅NSURLRequest的属性HTTPBodyStream)。使用流可以避免将所有POST数据加载到RAM中,这有助于缓解有限的RAM问题。

如果你有较小的POST数据,但可能有很多,你可以考虑使用NSOperationQueue放置NSOperation连接子类。将最大并发操作数设置为2.然后可以利用HTTP流水线 - 如果服务器支持此操作,这实际上可以减少延迟。

当然,您的应用中可能还有其他部分,例如您创建或检索必须发送的数据,这可能会影响整体性能。但是,如果你的代码是健全的,并且利用调度队列或NSOperations让事情在并行中执行,那么提供连接性能的选择就不多了。