Abd*_*tou 15 iphone concurrency objective-c grand-central-dispatch ios
场景:
为了显示警报视图并保持UI响应,我使用了dispatch_queue:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_sync(dispatch_get_main_queue(), ^{
// Show the alert view
});
});
Run Code Online (Sandbox Code Playgroud)使用以下命令启动地址簿修改过程:
dispatch_async(modifyingAddressBookQueue, ^{});
Run Code Online (Sandbox Code Playgroud)现在,我想让用户随时取消该过程(当然在保存地址簿之前).因此,当他点击警报表中的取消按钮时,我想访问调度块,设置一些特定的BOOL来停止进程并还原地址簿.
问题是,你做不到!您无法访问该块并更改其中的任何变量,因为所有变量只复制一次.块执行时块内变量的任何变化都不会被块看到.
总结一下:如何使用UI事件停止正在进行的操作?
更新:
该过程的代码:
- (void) startFixingModification {
_fixContacts = YES;
__block BOOL cancelled = NO;
dispatch_queue_t modifyingAddressBookQueue;
modifyingAddressBookQueue = dispatch_queue_create(sModifyingAddressBookQueueIdentifier,
NULL);
dispatch_async(modifyingAddressBookQueue, ^{
for (NSMutableDictionary *contactDictionary in _contactArray) {
if (!cancelled) {
break;
}
i = i + 1;
BOOL didFixContact = [self fixNumberInContactDictionary:contactDictionary];
if (!didFixContact) {
_fixedNumbers = _fixedNumbers - 1;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_sync(dispatch_get_main_queue(), ^{
[self setAlertViewProgress:i];
});
});
}
});
cancelledPtr = &cancelled;
}
Run Code Online (Sandbox Code Playgroud)
alertview代码(我自己的lib)委托
- (void) alertViewProgressCancel:(ASAlertViewProgress *)alertView { // This is a private lib.
if (cancelledPtr)
{
NSLog(@"stopping");
*cancelledPtr = YES;
}
}
Run Code Online (Sandbox Code Playgroud)
在界面中,我宣布
BOOL* cancelledPtr;
Run Code Online (Sandbox Code Playgroud)
更新2:
真的很令人沮丧!对于以下代码
for (NSMutableDictionary *contactDictionary in _contactArray) {
NSLog(@"%d", _cancelModification);
if (_cancelModification) {
break;
}
}
Run Code Online (Sandbox Code Playgroud)
如果_cancelModification设置为YES,则for循环被破坏,那就没问题.一旦我注释掉NSLog行,当_CancelModification变为YES时,忽略_cancelModification!
Kur*_*vis 20
如果声明BOOL使用__block,则可以在块执行之外进行更改,然后块将看到新值.有关详细信息,请参阅文档.
一个例子:
@interface SNViewController ()
{
BOOL* cancelledPtr;
}
@end
@implementation SNViewController
- (IBAction)start:(id)sender
{
__block BOOL cancelled = NO;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (!cancelled) {
NSLog(@"running");
sleep(1);
}
NSLog(@"stopped");
});
cancelledPtr = &cancelled;
}
- (IBAction)stop:(id)sender
{
if (cancelledPtr)
{
NSLog(@"stopping");
*cancelledPtr = YES;
}
}
@end
Run Code Online (Sandbox Code Playgroud)
或者,在班级中使用ivar来存储BOOL.该块将隐式地复制self并通过它访问ivar.没必要__block.
@interface SNViewController ()
{
BOOL cancelled;
}
@end
@implementation SNViewController
- (IBAction)start:(id)sender
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (!cancelled) {
NSLog(@"running");
sleep(1);
}
NSLog(@"stopped");
});
}
- (IBAction)stop:(id)sender
{
NSLog(@"stopping");
cancelled = YES;
}
@end
Run Code Online (Sandbox Code Playgroud)
创建一个返回"可取消"块的自定义dispatch_async方法.
// The dispatch_cancel_block_t takes as parameter the "cancel" directive to suspend the block execution or not whenever the block to execute is dispatched.
// The return value is a boolean indicating if the block has already been executed or not.
typedef BOOL (^dispatch_cancel_block_t)(BOOL cancelBlock);
dispatch_cancel_block_t dispatch_async_with_cancel_block(dispatch_queue_t queue, void (^block)())
{
__block BOOL execute = YES;
__block BOOL executed = NO;
dispatch_cancel_block_t cancelBlock = ^BOOL (BOOL cancelled) {
execute = !cancelled;
return executed == NO;
};
dispatch_async(queue, ^{
if (execute)
block();
executed = YES;
});
return cancelBlock;
}
- (void)testCancelableBlock
{
dispatch_cancel_block_t cancelBlock = dispatch_async_with_cancel_block(dispatch_get_main_queue(), ^{
NSLog(@"Block 1 executed");
});
// Canceling the block execution
BOOL success1 = cancelBlock(YES);
NSLog(@"Block is cancelled successfully: %@", success1?@"YES":@"NO");
// Resuming the block execution
// BOOL success2 = cancelBlock(NO);
// NSLog(@"Block is resumed successfully: %@", success2?@"YES":@"NO");
}
Run Code Online (Sandbox Code Playgroud)
如果条件已验证,则定义用于异步执行块的宏:
#define dispatch_async_if(queue,condition,block) \
dispatch_async(queue, ^{\
if (condition == YES)\
block();\
});
- (void)testConditionBlock
{
// Creating condition variable
__block BOOL condition = YES;
dispatch_async_if(dispatch_get_main_queue(), condition, ^{
NSLog(@"Block 2 executed");
});
// Canceling the block execution
condition = NO;
// Also, we could use a method to test the condition status
dispatch_async_if(dispatch_get_main_queue(), ![self mustCancelBlockExecution], ^{
NSLog(@"Block 3 executed");
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20961 次 |
| 最近记录: |