多个串行队列,UI 未更新

Multiple serial queues, UI not updating

我正在尝试 运行 一些密集型进程,使用多个串行队列。代码正在运行,但是我的 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 更新起作用但我尝试 "cleaner" 实施失败的串行队列有什么不了解?

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