场景:
- 用户点击一个按钮,要求对地址簿进行某种修改。
- 调用一个方法来开始此修改并显示一个警报 View 。
为了显示警报 View 并保持 UI 响应,我使用了 dispatch_queue:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_sync(dispatch_get_main_queue(), ^{ // Show the alert view }); });
使用以下命令启动地址簿修改过程:
dispatch_async(modifyingAddressBookQueue, ^{});
现在,我想为用户提供随时取消该过程的能力(当然是在保存地址簿之前)。所以当他点击警报表中的取消按钮时,我想访问调度 block ,设置一些特定的 BOOL 来停止进程并恢复地址簿。
问题是,你不能那样做!您无法访问该 block 并更改其中的任何变量,因为所有变量只复制一次。执行时 block 内变量的任何更改都不会被 block 看到。
总结:如何使用 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;
}
alertview(我自己的库)委托(delegate)的代码
- (void) alertViewProgressCancel:(ASAlertViewProgress *)alertView { // This is a private lib.
if (cancelledPtr)
{
NSLog(@"stopping");
*cancelledPtr = YES;
}
}
在接口(interface)中,我声明
BOOL* cancelledPtr;
更新 2:
真的很郁闷!对于以下代码
for (NSMutableDictionary *contactDictionary in _contactArray) {
NSLog(@"%d", _cancelModification);
if (_cancelModification) {
break;
}
}
如果 _cancelModification 设置为 YES,则 for 循环被破坏,这没关系。一旦我注释掉 NSLog 行,_cancelModification 在更改为 YES 时将被忽略!
最佳答案
如果您使用 __block
声明您的 BOOL
,那么它可以在 block 执行之外更改, block 将看到新值。参见 the documentation了解更多详情。
一个例子:
@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
或者,在您的类中使用一个 ivar 来存储 BOOL。该 block 将隐式复制 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
关于iphone - Objective-C,使用 UI 事件取消调度队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10066897/