UIView's drawRect not being called when swizzl

2019-07-04 08:18发布

问题:

I am experimenting with advanced Objective-C methods. What I want to achieve is to append specific drawing code to an existing UIView.

I started easily, I went on to declare my own drawRect method in a category:

@interface UIView (Swizzled)

- (void)my_drawRect:(CGRect)rect;

@end

Then I swizzled the drawRect method of UIView in the implementation of the category:

+ (void)load
{
    [self swizzleInstanceMethod:@selector(drawRect:) withMethod:@selector(my_drawRect:) inClass:[UIView class]];
}

- (void)my_drawRect:(CGRect)rect
{
    NSLog (@"Test.");
}

Implementation of this method is available on GitHub and the swizzling works in all other cases.

So according to the logic, every time drawRect is called, it should just print out "Test". But it does not work, the method I swizzled is never called. I went on to discover what I did wrong here, but the more I look at it, the more I believe the problem is somewhere else.

What if the drawRect method is not even called? I went on to try to force it being called:

view.contentMode = UIViewContentModeRedraw;
[view setNeedsDisplay];

Doesn't work either.

So my question is:

How to force UIView to call drawRect in this case or even my swizzled implementation?

Thanks!

回答1:

First, read to drawRect or not to drawRect (when should one use drawRect/Core Graphics vs subviews/images and why?)

Basically, UIView checks if you override drawRect: or not. If you don't override it, it can do lots of drawing optimizations and the method won't be even called.

In this case you didn't override it so UIView sees no reason to call it, even if you replaced the empty implementation with something else.