UIView backing layer - delegate is a zombie
I have a UIView class which uses a custom CALayer-derived backing layer. i.e., I have a static layerClass method which returns the class of my custom CALayer class.
+ (Class)layerClass
{
return [CellLayer class];
}
Within this class (CellLayer) I cast the delegate to the class of the UIView which contains the backing layer - specifically, within the drawInContext:
method I do this:
CellClass* cell = (CellClass*)self.delegate;
(where CellCass is a subclass of UIView)
This appears to work fine except that sometimes the drawInContext:
method is called and the delegate is a zombie (NSZombieEnabled is set TRUE).
It appears that what is happening is that when the cell object is removed from its superview (which is a UIScrollView) the cell is released before the backing layer is released and the backing layer gets a drawInContext:
call. NSLog statements reveal that BOTH dealloc methods are eventually called (ie. the UIView and the CALayer's dealloc are both called) but I can't tell for sure what order since the app using this has dozens and dozens of these cells - I guess I could change the NSLog to display the cell's address in the console and match up a UIVi开发者_StackOverflow中文版ew dealloc and a CALayer dealloc, but I haven't bothered to do this.
My expectation was that the backing layer would be released before the UIView which contains it.
Is this the correct behavior? My current workaround is that in the UIView's dealloc I set a flag in the backing layer (viewWasReleased
) and in the drawInContext I simply return if this flag is set.
Is there a better, cleaner way to do this?
today I had the same question and I finally fixed my problem.
The problem was that when the method dealloc is called, your CellLayer is not destroyed because it has a reference to the current object. (the delegate) So CALayer is not destroyed and the self.delegate is an deallocated instance. The zombie one.
I fixed that adding in my class viewDidDisappear method, and there I have added the next code:
if(cell != nil)
cell.delegate = nil;
Then when the dealloc method is called in my object there is not reference in CALayer to it so with a simple self.cell = nil; The CALayer object will be destroyed before and you won't have the problem with the delegate.
精彩评论