UIScrollView се срива, ако setContentOffset се извика с анимация

Моето приложение създава екземпляри на потребителски подклас на UIView и добавя тези екземпляри, разположени хоризонтално един до друг. Когато бъде създаден нов екземпляр на моя клас UIView, мога да го добавя към UIScrollView и да нулирам размера на съдържанието. След това се обаждам на [UIScrollView setContentOffset:(some point) animated:NO]. Това работи добре. Проблемът е, че когато извикам горепосочения метод с анимация, т.е. [UIScrollView setContentOffset:(some point) animated:YES], приложението се срива. Стекът за повиквания изглежда така:

> #0    0x3145b870 in ___forwarding___ ()
> #1    0x313b6650 in _CF_forwarding_prep_0 ()
> #2    0x317d84a2 in -[UIAnimator stopAnimation:] ()
> #3    0x317d84a2 in -[UIAnimator stopAnimation:] ()
> #4    0x317d7f0e in -[UIAnimator(Static) _advance:withTimestamp:] ()
> #5    0x317d7e00 in -[UIAnimator(Static) _LCDHeartbeatCallback:] ()
> #6    0x3531d86e in CA::Display::DisplayLink::dispatch(unsigned long long, unsigned long long) ()
> #7    0x3531d7c4 in CA::Display::IOMFBDisplayLink::callback(__IOMobileFramebuffer*,
> unsigned long long, unsigned long long, unsigned long long, void*) ()
> #8    0x33a56000 in IOMobileFramebufferVsyncNotifyFunc ()
> #9    0x36e3c60c in IODispatchCalloutFromCFMessage ()
> #10   0x31422f12 in __CFMachPortPerform ()
> #11   0x3142d522 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
> #12   0x3142d4c4 in __CFRunLoopDoSource1 ()
> #13   0x3142c312 in __CFRunLoopRun ()
> #14   0x313af4a4 in CFRunLoopRunSpecific ()
> #15   0x313af36c in CFRunLoopRunInMode ()
> #16   0x32888438 in GSEventRunModal ()
> #17   0x316b4cd4 in UIApplicationMain ()

Когато активирам Zombies, изходът на приложението произвежда:

*** -[__NSArrayM removeObject:]: message sent to deallocated instance 0x113dbb10

Допълнителна информация: Делегатът на UIScrollView никога не е зададен. Използвам ARC.


person Jude Pereira    schedule 13.08.2012    source източник


Отговори (2)


Намерих моя проблем. Извиквах метода, който извика setContentOffset от фонова нишка.

BackgroundThread --> My random processing method --> Setup new UIView and add it to UIScrollView --> Call setContentOffset with animations

Горният поток причинява срива. Когато извиках същия метод на обработка от основната нишка, той работи добре.

Очевидно iOS не харесва анимации, извикани от фонова нишка.

person Jude Pereira    schedule 14.08.2012
comment
Ако има едно правило за iOS и OSX, то никога не манипулира потребителския интерфейс на никоя нишка, освен на основната нишка. Правило #1. Не че не го харесва, а че е забранено и ябълкови документи това е повече от едно място. - person David H; 14.08.2012
comment
Да, забравих за факта, че извиквах този метод от фонова нишка. Просто реших да публикувам отговора си, в случай че някой е в същото разочароващо положение. - person Jude Pereira; 14.08.2012
comment
Не забравяйте да го изберете като отговор, когато SO ви позволи! Така че хората знаят, че въпросът е отговорен. - person David H; 14.08.2012

Един от изгледите в scrollView се освобождава. Вероятно го "прескачате", когато изключите анимацията - когато е включена, системата се опитва да получи поредица от "моментни снимки" на промените, а когато се опита да получи достъп до един изглед, бум надолу. Така че можете да активирате Zombies и да разберете точно какъв тип обект получава съобщението, а в програмата за отстраняване на грешки вероятно можете да "po" този обект.

Друг начин да го направим е да напишем собствена тестова анимация, да преместим contentOffset, да речем 20 пиксела наведнъж в цикъл без анимация, и да наблюдаваме, за да видим кога ще се срине (сигурно ще стане)!

person David H    schedule 13.08.2012
comment
Опитах ръчен цикъл и това не изглежда да създава проблеми, въпреки че екранът просто скочи до изместване без никаква анимация. Моят цикъл беше еквивалент на извикване на setContentOffset без анимация. - person Jude Pereira; 14.08.2012