3

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!

Legoless
  • 10,942
  • 7
  • 48
  • 68
  • Can you post the code for `swizzleInstanceMethod:withMethod:inClass:]`? – Austin May 22 '14 at 18:15
  • The code for this method is available at: [GitHub](https://github.com/Legoless/Haystack/blob/master/SDK/NSObject+Swizzle/NSObject+Swizzle.m), like written in the post above. It is irrelevant to this question though. – Legoless May 22 '14 at 18:18

1 Answers1

6

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.

Community
  • 1
  • 1
Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • This is a great illustration of the dangers of runtime reflection and metaprogramming. You use the runtime to change something, which doesn't have the expected behaviour because it breaks assumptions that someone else made when writing code that uses the runtime. A more vicious example of this is isa-swizzling an object that KVO also swizzles: http://stackoverflow.com/questions/11221110/my-isa-swizzling-breaks-kvo – Chris Devereux May 22 '14 at 18:44
  • Great resources, both of you. I'm assuming that `UIView` does more deep checks if `drawRect` is implemented and probably there is no way to force this. – Legoless May 22 '14 at 19:11