Objective-C,使用UI事件取消调度队列 [英] Objective-C, cancel a dispatch queue using UI event

查看:117
本文介绍了Objective-C,使用UI事件取消调度队列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景:


  • 用户点按一个按钮,要求对通讯录进行某种修改。

  • 调用一个方法来启动此修改,并显示一个警报视图。

  • 为了显示警报视图并保持UI响应,我使用dispatch_queue: p>

  • User taps a button asking for some kind of modification on address book.
  • A method is called to start this modification and an alert view is shown.
  • In order to show the alert view and keep the UI responsive, I used dispatch_queue:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                 dispatch_sync(dispatch_get_main_queue(), ^{
                   // Show the alert view
                 });
               });


  • 开始修改通讯录的过程:

  • Start the process of address book modification using:

    dispatch_async(modifyingAddressBookQueue, ^{});
    


  • 现在,随时取消过程的能力(当然在保存地址簿之前)。因此,当他点击警报表中的取消按钮时,我想访问调度块,设置某个BOOL来停止进程并还原地址簿。

    Now, I want to provide the user with the ability to cancel the process anytime (of course before saving the address book). So when he taps the cancel button in the alert sheet, I want to access the dispatch block, set some certain BOOL to stop the process and revert the address book.

    问题是,你不能这样做!您不能访问块并更改其中的任何变量,因为所有变量仅复制一次。

    The problem is, you can't do that! you can't access the block and change any variable inside it since all variables are copied only once. Any change of variables inside the block while being executed won't be seen by the block.

    总结:如何使用UI事件停止正在进行的操作?

    To sum up: How to stop a going operation using a UI event?

    更新:

    流程代码:

    - (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(my own lib)委托代码

    Code for alertview (my own lib) delegate

    - (void) alertViewProgressCancel:(ASAlertViewProgress *)alertView { // This is a private lib.
    
    
        if (cancelledPtr)
        {
            NSLog(@"stopping");
    
            *cancelledPtr = YES;
        }
    
    }
    



    在接口中,我声明



    In interface, I declare

    BOOL*   cancelledPtr;
    

    更新2:

    沮丧!

    for (NSMutableDictionary *contactDictionary in _contactArray) {
    
                NSLog(@"%d", _cancelModification);
                if (_cancelModification) {
                    break;
                }
    }
    

    如果_cancelModification设置为YES,for循环破碎,没关系。一旦我注释掉NSLog行,_cancelModification被忽略,当它更改为YES! 如果您使用声明 BOOL ,则

    if _cancelModification is set to YES, the for loop is broken and that's OK. Once I comment out the NSLog line, the _cancelModification is neglected when it changes to YES!

    推荐答案

    __block ,那么它可以在块执行之外更改,并且块将看到新的值。请参见

    If you declare your BOOL using __block, then it can be changed outside of the block execution, and the block will see the new value. See the documentation for more details.

    例如:

    @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。该块将隐式地创建一个 self 的副本,并将通过它访问该ivar。不需要 __ block

    Alternatively, use an ivar in your class to store the BOOL. The block will implicitly make a copy of self and will access the ivar via that. No need for __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
    

    这篇关于Objective-C,使用UI事件取消调度队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆