如何正确使用GCD在后台线程上做长进程,在主线程上做UI进程/更新



我正在处理这段代码,因为它阻塞了时间分析器报告的主线程。

OrderModule *module = [OrderModule sharedModule];
for(Modifier *modifier in modifierLists)
{
    int merge = [module getModifierMergeOption:modifier.mModifierId productId:product.mProductId];//long process database interaction
    for(ModifierItem *mod_product in modifier.activeModifiers)
    {
        NSString *modifierProductName = mod_product.productName;
        if (merge == 1) {
            modifierProductName = [modifierProductName stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@ - ",product.mProductName] withString:@""];
        }
        numberOfModifiers++;
        UILabel *modifierNameLabel = [[UILabel alloc] init];
        //            [modifierNameLabel setBackgroundColor:[UIColor redColor]];
        modifierNameLabel.lineBreakMode = UILineBreakModeWordWrap;
        modifierNameLabel.numberOfLines = 0;
        modifierNameLabel.lineBreakMode = NSLineBreakByWordWrapping;
        modifierNameLabel.numberOfLines = 0;
        [modifierNameLabel setFont:DEFAULT_FONT(DEFAULT_FONTSIZE_MODIFIERNAME)];
        modifierNameLabel.textColor = [UIColor colorWithRed:125.0f/255.0f green:127.0f/255.0f blue:131.0f/255.0f alpha:1.0f];
        //            modifierNameLabel.frame = CGRectMake(x, y, 140, 35);
        modifierNameLabel.frame = CGRectMake(x, y, 120, 35);
        modifierNameLabel.text = modifierProductName;
        [orderDetailRow addSubview:modifierNameLabel];

        UILabel *modifierAmount = [[UILabel alloc] init];
        [modifierAmount setFont:DEFAULT_FONT(DEFAULT_FONTSIZE_MODIFIERNAME)];
        modifierAmount.textColor = [UIColor colorWithRed:125.0f/255.0f green:127.0f/255.0f blue:131.0f/255.0f alpha:1.0f];
        //            modifierAmount.frame = CGRectMake(CGRectGetMaxX(modifierNameLabel.frame)+30, y, 100, 35);
        modifierAmount.frame = CGRectMake(CGRectGetMaxX(modifierNameLabel.frame)+6, y, 100, 35);
        [orderDetailRow addSubview:modifierAmount];
        //                modifiersCount++;
        amountPrice=amountPrice+([mod_product.mExtraCost floatValue]*count);
        [modifierAmount setText:[Utils currencyWithSymbol:[NSString stringWithFormat:@"%.02f",(([mod_product.mExtraCost floatValue]*count)+ 0.00001)]]];//simple manipulation
        if ([mod_product.mExtraCost floatValue]<=0) { //3.0 changes
            [modifierAmount setHidden:YES];
        }
        y = y + 25;
    }
    numberOfModifiers++;
}
[self setUpActiveModifierWithX:x andy:y Row:orderDetailRow andModifierList:modifierLists andProduct:product];

我已经试过了:

-(void)setUpModifierWithX:(float)x andy:(float)y Row:(OrderDetailRow *)orderDetailRow andModifierList:(NSMutableArray *)modifierLists andProduct:(Product *)product
{
    OrderModule *module = [OrderModule sharedModule];
    float __block Y = y;
    for(Modifier *modifier in modifierLists)
    {
        int __block merge;
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
             merge= [module getModifierMergeOption:modifier.mModifierId productId:product.mProductId];
            dispatch_async(dispatch_get_main_queue(), ^
            {
                for(ModifierItem *mod_product in modifier.activeModifiers)
                {
                    NSString *modifierProductName = mod_product.productName;
                    if (merge == 1) {
                        modifierProductName = [modifierProductName stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@ - ",product.mProductName] withString:@""];
                    }
                    numberOfModifiers++;
                    UILabel *modifierNameLabel = [[UILabel alloc] init];
                    //            [modifierNameLabel setBackgroundColor:[UIColor redColor]];
                    modifierNameLabel.lineBreakMode = UILineBreakModeWordWrap;
                    modifierNameLabel.numberOfLines = 0;
                    modifierNameLabel.lineBreakMode = NSLineBreakByWordWrapping;
                    modifierNameLabel.numberOfLines = 0;
                    [modifierNameLabel setFont:DEFAULT_FONT(DEFAULT_FONTSIZE_MODIFIERNAME)];
                    modifierNameLabel.textColor = [UIColor colorWithRed:125.0f/255.0f green:127.0f/255.0f blue:131.0f/255.0f alpha:1.0f];
                    //            modifierNameLabel.frame = CGRectMake(x, y, 140, 35);
                    modifierNameLabel.frame = CGRectMake(x, y, 120, 35);
                    modifierNameLabel.text = modifierProductName;
                    [orderDetailRow addSubview:modifierNameLabel];

                    UILabel *modifierAmount = [[UILabel alloc] init];
                    [modifierAmount setFont:DEFAULT_FONT(DEFAULT_FONTSIZE_MODIFIERNAME)];
                    modifierAmount.textColor = [UIColor colorWithRed:125.0f/255.0f green:127.0f/255.0f blue:131.0f/255.0f alpha:1.0f];
                    //            modifierAmount.frame = CGRectMake(CGRectGetMaxX(modifierNameLabel.frame)+30, y, 100, 35);
                    modifierAmount.frame = CGRectMake(CGRectGetMaxX(modifierNameLabel.frame)+6, y, 100, 35);
                    [orderDetailRow addSubview:modifierAmount];
                    //                modifiersCount++;
                    amountPrice=amountPrice+([mod_product.mExtraCost floatValue]*count);
                    [modifierAmount setText:[Utils currencyWithSymbol:[NSString stringWithFormat:@"%.02f",(([mod_product.mExtraCost floatValue]*count)+ 0.00001)]]];
                    if ([mod_product.mExtraCost floatValue]<=0) { //3.0 changes
                        [modifierAmount setHidden:YES];
                    }
                    Y = Y + 25;
                }
                numberOfModifiers++;
            });
        });

    }
    [self setUpActiveModifierWithX:x andy:y Row:orderDetailRow andModifierList:modifierLists andProduct:product];
}

但是setUpActiveModifierWithX:x在for循环结束执行之前被调用,我如何在for循环之后调用setUpActiveModifierWithX:x方法。

谢谢你的建议

我会从你正在做的退后一步,并学习如何使用TableViewController或CollectionViewController。

你似乎创建了非常多的子视图,这是一个昂贵的操作。表视图和集合视图通过反复重用相同的视图来避免这种情况,只是显示不同的值。而不是昂贵的视图,您使用更便宜的单元格。您还可以自动地只处理实际可见的内容,因此,如果您有1000个项目,则屏幕上只有12个项目会占用CPU时间。

最简单的修复方法是将它放在主线程上执行的块的最后一条语句之后:

编辑

下面的

将不起作用,不幸的是,如果不使用第三部分库,就没有"简单的修复"。我把答案留在这里是为了演示异步问题是如何迅速变得更复杂的。

-(void)setUpModifierWithX:(float)x andy:(float)y Row:(OrderDetailRow *)orderDetailRow andModifierList:(NSMutableArray *)modifierLists andProduct:(Product *)product
{
    OrderModule *module = [OrderModule sharedModule];
    float __block Y = y;
    for(Modifier *modifier in modifierLists)
    {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            int merge= [module getModifierMergeOption:modifier.mModifierId productId:product.mProductId];
            dispatch_async(dispatch_get_main_queue(), ^
            {
                for(ModifierItem *mod_product in modifier.activeModifiers)
                {
                   ...
                }
                numberOfModifiers++;

               [self setUpActiveModifierWithX:x andy:y Row:orderDetailRow andModifierList:modifierLists andProduct:product];
            });
        });
    }
}

事实证明,这个看似简单的任务实际上并不那么简单。我找不到比下面更简单的解决方案,不需要诉诸于第三方库,这使得这些任务更容易(稍后我会提出使用实用程序库的解决方案)。

因此,这里有一个使用递归块的方法。

递归块是很棘手的——除非你知道为什么和如何应用这种技术,否则我不建议使用它们。

代码片段显示了主要方法,但您的原始问题需要进行调整。

你的方法

-(void)setUpModifierWithX:(float)x andy:(float)y Row:(OrderDetailRow *)orderDetailRow andModifierList:(NSMutableArray *)modifierLists andProduct:(Product *)product

现在变成了一个异步方法:

-(void) foo
{
    NSArray* array = @[@"a", @"b", @"c"];  // your input array, e.g. "modifierLists"
    NSMutableArray* marray = [array mutableCopy]; // we need a mutable array here
    typedef void (^completion_t)(id result);
    typedef void (^block_t)(NSMutableArray*, completion_t);
    // setting up block variable suitable for using that block recursively:
    __block __weak block_t weak_block;
    block_t block;
    weak_block = block  = ^(NSMutableArray*array, completion_t completion) {
        // Check the termination condition for the "loop"
        if ([array count] == 0) {
            if (completion) {
                completion(@"Finished");
            }
            return;
        }
        id item = array[0]; 
        [array removeObjectAtIndex:0];
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            // process "item" on a secondary thread (private queue):
            int merge = [item characterAtIndex:0]; //[module getModifierMergeOption:modifier.mModifierId productId:product.mProductId];
            dispatch_async(dispatch_get_main_queue(), ^{
                // On the main thread, setup the UIKit objects:
                NSLog(@"%d", merge);
                /*
                for(ModifierItem *mod_product in modifier.activeModifiers)
                {
                    ...
                }
                numberOfModifiers++;
                */
                // Continue the loop:
                weak_block(array, completion);  //looks scary!
            });
        });
    };

    // Start the loop:
    block(marray, ^(id result){
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"result: %@", result);
            //[self setUpActiveModifierWithX:x andy:y Row:orderDetailRow andModifierList:modifierLists andProduct:product];
        });
    });
}

关于递归块,请参阅递归块中的ARC行为问题和SO上的答案:https://stackoverflow.com/a/19626441/465677

相关内容

  • 没有找到相关文章

最新更新