Lor*_*o B 4 background nsoperation nsoperationqueue ios
我在制定有用的策略以支持NSOperationQueue课堂背景时遇到了一些问题.特别是,我有一堆NSOperations执行以下操作:
操作将插入到串行队列中.一旦操作完成,下一个操作就可以开始了.
当应用程序进入后台时,我需要停止(或继续)操作.从这些讨论(AFNetworking是否有后台支持?和NSOperations的队列以及处理应用程序退出)我看到最好的方法是取消操作并isCancelled在每个操作中使用属性.然后,检查针对该属性的操作的关键点,它允许在应用程序进入后台时回滚执行(运行操作的)的状态.
基于突出背景支持的Apple模板,我该如何管理类似情况?我可以简单地取消操作或等待当前操作完成吗?请参阅评论了解详情
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
// Do I have to call -cancelAllOperations or
// -waitUntilAllOperationsAreFinished or both?
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// What about here?
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
Run Code Online (Sandbox Code Playgroud)
先感谢您.
编辑
如果NSOperation main方法执行下面的代码,如何遵循响应取消事件模式?
- (void)main
{
// 1- download
// 2- parse
// 2.1 read file location
// 2.2 load into memory
// 3- import
// 3.1 fetch core data request
// 3.2 if data is not present, insert it (or update)
// 3.3 save data into persistent store coordinator
}
Run Code Online (Sandbox Code Playgroud)
我描述的每个方法都包含各种步骤(非原子操作,下载除外).因此,在这些步骤的每一步中都可能发生取消(以非预定义的方式).我可以isCancelled在每一步之前检查一下房产吗?这有用吗?
根据Tammo Freese编辑编辑2
我理解你的编辑代码是什么意思.但我担心的是以下几点.取消请求(用户可以按下主页按钮)可以在main执行中的任何时刻发生,因此,如果我简单地返回,则操作的状态将被破坏.在返回之前我需要清理它的状态吗?你怎么看?
我描述的问题可能发生在我使用同步操作时(在他们运行的同一个线程中以同步方式执行的操作).例如,如果main正在下载文件(通过执行下载+sendSynchronousRequest:returningResponse:error)并且应用程序放在后台,那会发生什么?如何管理这种情况?
// download
if ([self isCancelled])
return;
// downloading here <-- here the app is put in background
Run Code Online (Sandbox Code Playgroud)
显然,我认为当应用程序放在前台时,操作会再次运行,因为它已被取消.换句话说,它被迫不能保持其状态.我错了吗?
Tam*_*ese 15
如果我理解正确,你有一个NSOperationQueue,如果你的应用程序进入后台,你想
通常这不应该花太多时间,所以这应该足够了:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[_queue cancelAllOperations];
[_queue waitUntilAllOperationsAreFinished];
}
Run Code Online (Sandbox Code Playgroud)
这里"太多时间"的定义大约是五秒钟:如果您阻止的-applicationDidEnterBackground:时间长于此时间,您的应用程序将被终止并从内存中清除.
假设完成取消的操作需要的时间超过5秒.然后你必须在后台等待(参见注释的解释):
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
// If this block is called, our background time of normally 10 minutes
// is almost exceeded. That would mean one of the cancelled operations
// is not finished even 10 minutes after cancellation (!).
// This should not happen.
// What we do anyway is tell iOS that our background task has ended,
// as otherwise our app will be killed instead of suspended.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Normally this one is fast, so we do it outside the asynchronous block.
[_queue cancelAllOperations];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Wait until all the cancelled operations are finished.
[_queue waitUntilAllOperationsAreFinished];
// Dispatch to the main queue if bgTask is not atomic
dispatch_async(dispatch_get_main_queue(), ^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
});
}
Run Code Online (Sandbox Code Playgroud)
所以基本上我们告诉iOS我们需要一些时间来执行任务,当任务完成时间耗尽时,我们告诉iOS我们的任务已经结束.
编辑
要回答编辑中的问题:要响应取消,只需在可能的情况下检查取消,然后从-main方法返回.取消的操作不会立即完成,但会在-main返回时完成.
- (void)main
{
// 1- download
if ([self isCancelled]) return;
// 2- parse
// 2.1 read file location
// 2.2 load into memory
while (![self isCancelled] && [self hasNextLineToParse]) {
// ...
}
// 3- import
// 3.1 fetch core data request
if ([self isCancelled]) return;
// 3.2 if data is not present, insert it (or update)
// 3.3 save data into persistent store coordinator
}
Run Code Online (Sandbox Code Playgroud)
如果您根本没有检查取消的标志-main,则操作不会对取消作出反应,而是一直运行直到完成.
编辑2
如果操作被取消,除了isCancelled标志设置为true之外没有任何反应.我的原始答案中的上述代码在后台等待,直到操作完成(或者对取消作出反应或者简单地完成,假设它不需要10分钟来取消它).
当然,在对isCancelled我们的操作做出反应时,您必须确保将操作保持在未损坏的状态,例如,在下载后直接(只是忽略数据),或者在写入所有数据之后.
你是对的,如果一个操作被取消但是当你切换回前台时仍然运行,那个操作将完成下载,然后(如果你这样编程)反应取消并基本上丢弃下载的数据.
你可以做的不是取消操作,而是等待它们完成(假设它们不到10分钟).要做到这一点,只需删除该行[_queue cancelAllOperations];.
| 归档时间: |
|
| 查看次数: |
7549 次 |
| 最近记录: |