多个串行队列,UI不更新

时间:2015-11-11 16:32:04

标签: ios multithreading serialization queue grand-central-dispatch

我正在尝试使用多个串行队列连续运行一些密集型进程。代码正在运行,但即使调用该方法,我的UI更新也不会发生。

以下是以串行方式运行多个进程的代码。

- (void)importProcess {
    dispatch_queue_t serialQueue = dispatch_queue_create("com.cyt.importprocessqueue", DISPATCH_QUEUE_SERIAL);

    NSLog(@"checking image sizes");
    __block NSMutableArray *assets;
    dispatch_sync(serialQueue, ^() {
        assets = [self checkImageSizes];
    });

    dispatch_sync(serialQueue, ^() {
        [self appendLogToTextView:[NSString stringWithFormat:@"%i screenshot(s) ignored due to invalid size.",(int)(self.assets.count-assets.count)]];
        if(assets.count==0) {
            [self showNoRunesFoundAlert];
        }
        else {
            [self appendLogToTextView:@"Preparing to process screenshots..."];
            self.assets = [NSArray arrayWithArray:assets];
        }
    });

    NSLog(@"processing uploads");
    dispatch_sync(serialQueue, ^() {
        [self processUploads];
    });

    NSLog(@"recognizing images");
    dispatch_sync(serialQueue, ^() {
        [self recognizeImages];
    });

    NSLog(@"recognizing images");
    dispatch_sync(serialQueue, ^() {
        [self processRuneText];
    });
    //dispatch_sync(dispatch_get_main_queue(), ^ {

    //});
}

checkImageSizes内,我有另一个串行队列:

- (NSMutableArray *)checkImageSizes {
    dispatch_queue_t serialQueue = dispatch_queue_create("com.cyt.checkimagesizequeue", DISPATCH_QUEUE_SERIAL);
    NSMutableArray *assets = [NSMutableArray new];

    for(int i=0;i<self.assets.count;i++) {
        dispatch_sync(serialQueue, ^{
            PHAsset *asset = (PHAsset *)self.assets[i];
            if(asset.pixelWidth==self.screenSize.width && asset.pixelHeight==self.screenSize.height) {
                [assets addObject:asset];
                NSString *logText = [NSString stringWithFormat:@"Screenshot %i/%i size is OK.",i+1,(int)self.assets.count];
                [self performSelectorOnMainThread:@selector(appendLogToTextView:) withObject:logText waitUntilDone:YES];
            }
            else {
                [self appendLogToTextView:[NSString stringWithFormat:@"ERROR: Screenshot %i/%i has invalid size. Skipping...",i+1,(int)self.assets.count]];
            }
        });
    }
    return assets;
}

appendLogToTextView方法应该更新UI。这是代码:

- (void)appendLogToTextView:(NSString *)newText {
    dispatch_block_t block = ^ {
        self.logText = [NSString stringWithFormat:@"%@\n%@", self.logText, newText];
        NSString *textViewText = [self.logText substringFromIndex:1];
        [UIView setAnimationsEnabled:NO];
        if(IOS9) {
            [self.textView scrollRangeToVisible:NSMakeRange(0,[self.textView.text length])];
            self.textView.scrollEnabled = NO;
            self.textView.text = textViewText;
            self.textView.scrollEnabled = YES;
        }
        else {
            self.textView.text = textViewText;
            NSRange range = NSMakeRange(self.textView.text.length - 1, 1);
            [self.textView scrollRangeToVisible:range];
        }
        [UIView setAnimationsEnabled:YES];
    };
    if ([NSThread isMainThread]) {
        block();
    }
    else {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}

正如您所看到的,我尝试直接调用appendLogToTextView并使用performSelectorOnMainThread。但是,即使我确认正确调用了该方法,我也没有对文本视图进行任何更新。

有趣的是,当我只使用单个串行队列并使用迭代计数来调用下一个方法时,UI更新正常工作,如下面的代码所示(_serialQueue在viewDidLoad中定义)。但是,我不相信实现是好的做法,因为我在串行队列中包装串行队列。

- (void)checkImageSizes {
    NSMutableArray *assets = [NSMutableArray new];
    for(int i=0;i<self.assets.count;i++) {
        dispatch_async(_serialQueue, ^{
            PHAsset *asset = (PHAsset *)self.assets[i];
            if(asset.pixelWidth==self.screenSize.width && asset.pixelHeight==self.screenSize.height) {
                [assets addObject:asset];
                [self appendLogToTextView:[NSString stringWithFormat:@"Screenshot %i/%i size is OK.",i+1,(int)self.assets.count]];
            }
            else {
                [self appendLogToTextView:[NSString stringWithFormat:@"ERROR: Screenshot %i/%i has invalid size. Skipping...",i+1,(int)self.assets.count]];
            }

            //request images
            if(i==self.assets.count-1) {
                [self appendLogToTextView:[NSString stringWithFormat:@"%i screenshot(s) ignored due to invalid size.",(int)(self.assets.count-assets.count)]];
                if(assets.count==0) {
                    [self showNoRunesFoundAlert];
                }
                else {
                    [self appendLogToTextView:@"Preparing to process screenshots..."];
                    self.assets = [NSArray arrayWithArray:assets];
                    [self processUploads];
                }
            }
        });
    }
}

我不了解导致此版本代码中的UI更新工作的串行队列,但我尝试“更清洁”的实现失败了?

1 个答案:

答案 0 :(得分:0)

最后,我最终使用了调度组和完成块来解决这个问题。