Предварительно загрузить / отобразить плитки в CATiledLayer?

На iPhone (хотя я полагаю, что это не менее актуальный вопрос для Какао) у меня есть UIScrollView вокруг UIView, поддерживаемого CATiledLayer. По умолчанию он работает с загрузкой любых некэшированных / невыгруженных плиток, когда мое окно просмотра прокручивается по пустому разделу CATiledLayer.

Я хотел бы знать, есть ли способ запустить CATiledLayer для загрузки плитки, которая не отображается активно? Я хотел бы, например, предварительно загрузить все плитки, прилегающие к текущей отображаемой плитке, пока они все еще находятся за пределами экрана, чтобы избежать мигания пустого экрана, который исчезает с изображением после его асинхронной загрузки.

Любые идеи?


person jemmons    schedule 15.07.2009    source источник
comment
Вы в этом разобрались? Я действительно хотел бы знать, как вы это сделали, если да.   -  person Drew McCormack    schedule 27.04.2010
comment
Неа. Никогда не делал. :( Использование setNeedsDisplayInRect: работает для обновления содержимого уже загруженной плитки, но не вызывает ее предварительной загрузки.   -  person jemmons    schedule 29.04.2010


Ответы (3)


Не думаю, что CATiledLayer будет делать то, что вы хотите. Однако есть несколько других вариантов. Сначала вы можете отключить постепенное появление плитки и сразу же отобразить ее примерно так:

@interface NoFadeTiledLayer : CATiledLayer {
}
@end

@implementation NoFadeTiledLayer
+ (CFTimeInterval)fadeDuration {
    return 0.0;
}
@end

@implementation MyViewWithTiledLayer
+ (Class)layerClass {
    return [NoFadeTiledLayer class];
}
...
@end

Во-вторых, вы можете выполнять предварительную выборку и кэширование соседних плиток, чтобы они были готовы к работе, когда CATileLayer вызывает drawLayer: inContext. Я бы реализовал scrollViewDidScroll: и scrollViewDidZoom: для определения соседних плиток и levelOfDetail. Затем выполните поиск в кеше и добавьте отсутствующие в очередь предварительной выборки / рендеринга. Фоновый поток мог бы обслуживать очередь, и последующие прокрутки или масштабирование очистили бы и перестроили очередь. Затем сделайте drawLayer: inContext сначала проверьте кеш и, если необходимо, выберите только выборку / рендеринг.

person John Lemberger    schedule 01.03.2011
comment
Я пробовал этот подход к предварительному кэшированию (включая подкласс слоя no-fade-duration), и, к сожалению, он не очень помогает. Я не понимаю, почему; это определенно звучит как хороший подход. - person Seamus Campbell; 17.03.2011

CATileLayer - один из тех разочаровывающих классов, где он отлично справляется с одной задачей, но не имеет гибкости.

На этом этапе все, что нам осталось, - это творчество:

1) Сделайте вид прокрутки огромным. Я попробовал увеличить размер экрана в 5 раз, прежде чем перестал видеть «пустые» плитки. Остерегайтесь использования памяти! Вы рисуете огромную область, хотя пользователь видит только 2% от нее.

2) Имейте две версии вашего изображения, одну в высоком разрешении и одну в низком разрешении. вы должны иметь возможность очень быстро менять низкое разрешение, и в основном вы получаете «размытые» вместо «пустых» плиток. Пример кода Apple ZoomingPDFViewer показывает, как это сделать.

http://developer.apple.com/library/ios/#samplecode/ZoomingPDFViewer/Introduction/Intro.html

Конечно, комбинация того и другого может сработать, если вы хотите потратить время.

person amattn    schedule 28.02.2011
comment
Все отличные идеи. Хотел бы я назвать два ответа! - person jemmons; 05.03.2011

Вам следует попробовать вызвать setNeedsDisplayInRect: для областей, которые вы хотите отобразить. Если вы хотите сохранить границы плитки, вы можете использовать свойство tileSize для вычисления границ плитки.

Но я не знаю точно, сработает ли это, и мы не знаем, как работает механизм кеширования тайлов.

person Jon Steinmetz    schedule 15.07.2009