С помощью Grand Central Dispatch вы можете планировать чтение и запись, не беспокоясь о том, когда и как это произойдет. По сравнению с моим предыдущим подходом, основанным на NSStream, для этого требуется меньше внешнего управления. Однако моя наивная реализация медленнее, чем мой подход, основанный на NSStream.
Для NSStream я запросил предпочтительный размер ввода-вывода как источника, так и получателя ( NSURLPreferredIOBlockSizeKey
).Затем я читал целые «предпочтительные фрагменты входного размера» в буфер, и как только у меня было хотя бы байтов «предпочтительного выходного размера» в буфере, я записывал целые фрагменты в пункт назначения (кроме последнего фрагмента, конечно). Это должно быть довольно близко к оптимальному в отношении производительности чтения и записи.
Тем не менее, с НОД я не имею большого влияния на это. Представьте, что источник имеет предпочтительный размер ввода-вывода 100 КБ, а целевой размер предпочтительного ввода-вывода для цели составляет 1 МБ: моя наивная реализация теперь будет записывать в 10 раз чаще, чем в моем решении на основе NSStream.
Итак, какой самый эффективный способ решить эту проблему с помощью НОД? Просто записать в буфер в блоке чтения, и как только будет собрано достаточно данных, запланировать блок записи «предпочтительного размера вывода»? Я предполагаю, что GCD может предложить мне решение, о котором я еще не знаю.
Вот самая важная часть моего текущего решения НОД:
// input_ and output_ are of type dispatch_io_t
dispatch_io_read(
input_,
0,
SIZE_MAX,
dispatch_get_main_queue(),
^(bool done, dispatch_data_t data, int error) {
size_t data_size;
if (error) {
NSLog(@"Input: error %d", error);
[self cancel];
return;
}
if (data) {
data_size = dispatch_data_get_size(data);
if (data_size > 0) {
dispatch_io_write(
output_,
0,
data,
dispatch_get_main_queue(), ^(bool done, dispatch_data_t data, int error) {
// TODO: I don't know how to get the offset (for progress). So I need to
// pass it from the calling block.
if (error) {
NSLog(@"Output: error %d", error);
return;
}
if (done) {
bytesWritten_ += data_size;
// Update progress report here.
}
}
);
}
}
}
);