繁体   English   中英

在iOS中高效同步数据

[英]Efficiently sync data in iOS

当应用程序进入后台并且应用程序处于活动状态时,我正在与服务器之间来回同步数据的应用程序上工作。 因为当我同步到多个设备时,应该在所有设备上更新数据。

所以这就是我的做法

- (void)applicationDidBecomeActive:(UIApplication *)application
{
     if([[AppManager instance].globalManager activeSyncCounter] == 0)
     {
           [_webService callServerAPI];         
     }
}


- (void)applicationDidEnterBackground:(UIApplication *)application
{
    if([[AppManager instance].globalManager activeSyncCounter] == 0)
     {
           [_webService callServerAPI];         
     }
}

让我解释一下上面的代码

1)我正在调用API来同步我的数据,我遍历for循环以同步我的数据并将其发送到服务器。(所有调用都是异步的)

2)如您所见,我已经使用了activeSyncCounter 我之所以这样使用,是因为用户可以立即打开和退出该应用程序,这样直到第一个完成时才可以再次调用服务器API。

现在这是我的疑问。

1)首先,当我收到来自服务器的响应时,当数据更多时,通过for循环进行更新需要花费时间,并且我的UI变得无响应。 因此,为了对此进行改进,我需要在调度队列中运行for循环代码。 还是他们有其他更好的方法吗?

另外,更新完成后,当应用程序进入后台时,我是否需要在应用程序进入后台时调度队列?

2)其次,它们是使用activeSyncCounter的替代方法吗?

您(几乎)永远都不想在主线程上执行任何同步I / O操作(包括网络操作),因此对您来说,第一个问题是,您应该使用异步联网API或将同步操作移至其他线程-派遣队列是做到这一点的一种方法。

关于您的第二个问题,我不知道肯定存在“更好”的方式,但是有不同的方式。 我可能建议的一件事是将检查移到callServerAPI ,以简化调用该方法的代码。 (即,一次编写检查代码,而不是在调用服务器API的任何地方编写。)

重要的是,通过调用完成模块来构建网络操作以运行异步并完成操作。 NSURLConnection提供了一个名为sendAsynchronousRequest:completionHandler:的便捷方法,该方法就可以做到这一点。

由于您要完成的某些工作必须在进入后台后完成,因此您的应用程序必须保持足够长的生命周期才能完成。 苹果在这里提供了完整的文章 ,但要旨是(针对您的情况调整了示例代码)...

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
        // Clean up any unfinished task business by marking where you
        // stopped or ending the task outright.
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];

    // this is your call, modified to use a completion block
    [_webService callServerAPIWithCompletion:^(id result, NSError *error) {
        // set state to indicate that the synch finished...see below
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;        
    }];  
}

因此,我认为您有两个工作要做:(1)​​重构网络代码以通过调用一个块来异步运行并完成操作;(2)提出一种方案来限制您运行网络请求的频率。

关于后一点,请考虑将NSDate保存到NSUserDefaults。 然后您可以问:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDate *lastSynch = [defaults objectForKey:@"MyApp_lastSynch"];

NSTimeInterval sinceLastSynch = -[lastSynch timeIntervalSinceNow];
if (sinceLastCheck < 3600) {
    // we did the last synch less than an hour ago.  skip it for now
} else {
   // do it
}

在同步的完成块中,记下当前的完成时间:

 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSDate date] forKey:@"MyApp_lastSynch"];
[defaults synchronize];

编辑 -这是您的网络代码使用块时的外观:

- (void)pushDataWithCompletion:(void (^)(BOOL, NSError))completion;

综合所有这些,您的应用程序委托代码可能看起来最好像这样:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // don't bother if we did this recently (60 sec in this e.g.
    if ([self timeSinceLastPushData] < 60) return;

    bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];

    // this is your call, modified to use a completion block
    [pushDataWithCompletion:^(BOOL success, NSError *error) {
        if (success) {
             NSLog(@"success.  right down the time");
             [self pushDataComplete];
        } else {
            NSLog(@"error %@, but we'll still tell os that we're done", error);
        }
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;        
    }];  
}

- (void)pushDataComplete {
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:[NSDate date] forKey:@"MyApp_lastSynch"];
    [defaults synchronize];
}

- (NSTimeInterval)timeSinceLastPushData {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSDate *lastSynch = [defaults objectForKey:@"MyApp_lastSynch"];

    return -[lastSynch timeIntervalSinceNow];
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM