Не съм гледал разглобяването, за да видя, но използваме малко по-различно решение. Задаването на свойството CATiledLayer.content
на nil
блокира и принуждава всички блокове за изобразяване на опашка да завършат. Това може безопасно да се прехвърли към фонова нишка, след което пускането на UIView
може да бъде върнато обратно към основната нишка, за да позволи на изгледа и слоя да се освободи.
Ето един пример за UIViewController dealloc
внедряване, което ще поддържа вашия CATiledLayer
притежаващ изглед жив достатъчно дълго, за да спре безопасно изобразяването, без да блокира основната нишка.
- (void)dealloc
{
// This works around a bug where the CATiledLayer background drawing
// delegate may still have dispatched blocks awaiting rendering after
// the view hierarchy is dead, causing a message to a zombie object.
// We'll hold on to tiledView, flush the dispatch queue,
// then let go of fastViewer.
MyTiledView *tiledView = self.tiledView;
if(tiledView) {
dispatch_background(^{
// This blocks while CATiledLayer flushes out its queued render blocks.
tiledView.layer.contents = nil;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// Make sure tiledView survives until now.
tiledView.layer.delegate = nil;
});
});
}
}
Това е предположение, но някои от рамките/класовете на Apple (StoreKit, CATiledLayer, UIGestureRecognizer) твърдят, че имат @property (weak) id delegate
реализации, но очевидно не обработват правилно weak
делегата. Гледайки някакво разглобяване и те правят определено обвързани със състезание if != nil
проверки, след което директно докосват слабото свойство. Правилният начин е да декларирате __strong Type *delegate = self.delegate
, което или ще успее и ще ви даде силна препратка, гарантирана за оцеляване, или ще бъде nil
, но със сигурност няма да ви даде препратка към зомби обект (моят предполагам, че кодът на рамката не е надстроен до ARC).
Под капака CATiledLayer
създава опашка за изпращане, за да извърши изобразяването във фонов режим и изглежда или докосва свойството на делегата по опасен начин, или получава локална препратка, но без да я прави силна. Така или иначе, изпратените рендерни блокове с радост ще изпратят съобщение за зомби обект, ако делегатът бъде освободен. Самото изчистване на делегата е недостатъчно - това ще намали броя на сривовете, но не ги елиминира безопасно.
Настройването на content = nil
прави dispatch_wait и блокира, докато не завършат всички съществуващи блокове за изобразяване на опашка. Връщаме се към основната нишка, за да се уверим, че dealloc
е безопасно.
Ако някой има предложения за подобрение, моля да ме уведомите.
person
russbishop
schedule
01.12.2014