добавление UIImageView в UIScrollview с большим потоком блоков изображения - PullRequest
4 голосов
/ 25 ноября 2010

Я загружаю изображение в UIImageView, которое затем добавляю в UIScrollView. Изображение является локальным и имеет высоту около 5000 пикселей.

Проблема в том, что когда я добавляю UIImageView в UIScrollView, поток блокируется. Это очевидно, потому что, когда я делаю это, я не могу прокрутить UIScrollView, пока изображение не отобразится.

Вот пример.

UIScrollView *myscrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 768, 1004)];
myscrollview.contentSize = CGSizeMake(7680, 1004);
myscrollview.pagingEnabled = TRUE;

[self.view addSubview:myscrollview];

NSString* str = [[NSBundle mainBundle] pathForResource:@"APPS.jpg" ofType:nil inDirectory:@""];
NSData *imageData = [NSData dataWithContentsOfFile:str];
UIImageView *singleImageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData:imageData]];

    //the line below is the blocking line
[scrollView addSubview:singleImageView];

Это последняя строка в скрипте, которая блокирует скроллер. Когда я опускаю это, все работает отлично, за исключением того факта, что изображение не показывает, конечно.

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

Спасибо за вашу помощь.

Ответы [ 3 ]

1 голос
/ 25 ноября 2010

Если вы предоставляете эти большие изображения, вам, возможно, стоит проверить CATiledLayer; есть видео хорошей презентации о том, как использовать это из WWDC 2010.

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

  • создать контекст рисования с помощью CGBitmapContextCreate
  • нарисуйте свое изображение так же, как вы рисуете на экране в drawRect:
  • когда вы закончите загрузку и отрисовку изображения, вызовите drawRect: метод вашего представления в главном потоке, используя executeSelectorOnMainThread: withObject: waitUntilDone:

В методе drawRect: вашего представления после того, как вы полностью нарисовали изображение в контексте в памяти, скопируйте его на экран, используя CGBitmapContextCreateImage и CGContextDrawImage.

Это не тривиально, вам нужно запустить фоновый поток в нужное время, синхронизировать доступ к вашим изображениям и т. Д. Подход CATiledLayer почти наверняка лучше, если вы можете найти способ манипулировать изображениями. чтобы сделать эту работу.

0 голосов
/ 29 ноября 2010

Попробуйте выделить UIImageView без UIImage и добавить его в качестве вложенного представления в UIScrollView.

Загрузить UIImage в отдельном потоке и запустить метод в другом потоке, чтобы установить изображениесвойство UIImageView, когда изображение загружается в память.Также вы, вероятно, столкнетесь с некоторыми проблемами с памятью, поскольку изображение такого размера, загруженное в UIImage, вероятно, будет 30 МБ +

UIScrollView *myscrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 768, 1004)];
myscrollview.contentSize = CGSizeMake(7680, 1004);
myscrollview.pagingEnabled = TRUE;

[self.view addSubview:myscrollview];

NSString* str = [[NSBundle mainBundle] pathForResource:@"APPS.jpg" ofType:nil inDirectory:@""];
UIImageView *singleImageView = [[UIImageView alloc] init];

[scrollView addSubview:singleImageView];

//Then fire off a method on another thread to load the UIImage and set the image
//property of the UIImageView.

Просто следите за памятью и остерегайтесь использования удобных конструкторов с UIImage (или любым другим объектомэто может оказаться огромным)

Кроме того, где вы в настоящее время запускаете этот код?

0 голосов
/ 25 ноября 2010

Почему вы хотите загрузить такое огромное изображение в память одновременно?разделите его на множество маленьких изображений и динамически загружайте / освобождайте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...