В моем приложении я обрабатываю партии (от 200 до 400) UIImage
s на фоновом потоке, а затем устанавливаю их внутри на экране UIImageView
экземпляров, отправив блок обновления пользовательского интерфейса в основной поток.Безопасность на экране UIView
Некоторый код, чтобы показать примерно то, что я делаю ...
dispatch_async(redrawQueue, ^{
// An array to stuff images in to for the views that have one.
NSMutableArray *const images = [NSMutableArray arrayWithCount: [activeViews count] value: [NSNull null]];
for(NSUInteger i=0; i<activeCount; ++i)
{
// Rendered content comes from a block in myState.
UIImage *const image = contentBlock(i);
if(image)
{
images[i] = image;
}
}
else
{
return;
}
// Update the UI now…
dispatch_async(dispatch_get_main_queue(), ^{
[images enumerateObjectsUsingBlock:^(UIImage *image, NSUInteger i, BOOL *stop) {
UIImageView *const view = [activeViews objectAtIndex:i];
[view setImage: [NSNull isNotNull: image] ? image : nil];
layoutBlock(view, i);
}];
});
});
Это работает хорошо, но я до сих пор теряюсь кадры во время быстрой прокрутки. Похоже, это происходит потому, что работа по настройке изображений в представлениях подавляет основной поток. Мое свидетельство для этого состоит в том, что, если я выберу только код, чтобы на самом деле установить отображаемые изображения в представлениях, прокрутка намного более плавная.
Мне интересно, может ли подход к решению этого вопроса также создать представления в фоновом потоке, назначить им изображения и поместить их в представление контейнера. Затем в основном потоке мне просто нужно было бы поменять контейнер на сцену. Результат немного похож на двойной буферный графический контекст, я думаю - обновите его, пока отображается другое.
Может кто-нибудь предложить, если это вряд ли будет потокобезопасным?
Я сделал небольшой тест на выделение экранов UIViews на фоновый поток и вложен их друг в друга. Он еще не разбился :-) «Он еще не разбился», однако, это не отличная гарантия безопасности потока! Он также ничего не говорит о том, что может произойти в будущей версии iOS.
Очевидный ответ на это «Эй, ты, дурак, почему вы используете сотни маленьких взглядов? Композит их к одному большому изображению и иметь один вид вы поменять его на сайте.» К сожалению, мне нужно много маленьких просмотров, потому что мне нужно перемещать отдельные маленькие кусочки независимо.
Другой ответ может быть «Используйте спрайтов комплект, чувак», и вы, вероятно, правы, но маленькие точки зрения имеют динамический размер и содержание, и я не знаю, как оптимальный набор спрайтов, когда есть много появляются спрайты.
Третий подход может заключаться в том, чтобы дросселировать обновления пользовательского интерфейса в основном потоке, чтобы предотвратить падение кадров. Есть ли механизм, который это делает? Какая-то очередь отправки запускается основным потоком, который вызывает только мелочи, пока у него осталось много времени?
Для чего это стоит, я пробовал это. Это не сбой, но он не работает. Когда я добавляю предварительно заполненный вид контейнера (в основном потоке), содержимое не появляется. Он ошибочно начинает появляться через некоторое время, но не в какой-либо полезной или надежной форме. Вероятно, это не стартер. – Benjohn