如何正确使用GCD对maion线程上的后台线程和UI进程/更新进行长时间的处理

时间:2014-03-14 14:11:38

标签: iphone ipad grand-central-dispatch

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

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];

}

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

感谢您的任何建议

3 个答案:

答案 0 :(得分:0)

我退出你正在做的事情,并学习如何使用TableViewController或CollectionViewController。

您似乎正在创建大量子视图,这是一项昂贵的操作。表视图和集合视图通过反复重复使用相同的视图来避免这种情况,只显示不同的值。而不是昂贵的视图,你使用更便宜的细胞。您还自动只处理实际可见的内容,因此如果您有一千个项目,屏幕上只有十几个会占用CPU时间。

答案 1 :(得分:0)

最简单的解决方法是将它放在主线程上执行的块中的最后一个语句之后:

修改

以下内容不会起作用,不幸的是,没有&#34;轻松修复&#34;没有使用第三个部分库。我在这里留下答案,用于演示异步问题如何迅速变得复杂。

-(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];
            });
        });
    }
}

答案 2 :(得分:0)

事实证明,这个看似简单的任务实际上并不那么容易。我找不到比以下更简单的解决方案,没有诉诸第三方库,这使得这些任务变得更加容易(我将提出一个使用实用程序的解决方案)图书馆稍后)。

所以,这是一种使用递归块的方法。

警告

  

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

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

你的方法

-(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 behavior within a recursive block,并在SO:https://stackoverflow.com/a/19626441/465677

上找到此答案