UIView overriding drawRect causes view not to obey masksToBounds

不羁岁月 提交于 2019-12-04 04:53:34
AlexChaffee

I don't know the full answer, but I do know that UIView's implementation of drawLayer:inContext: works differently depending on whether you have implemented drawRect: or not. Perhaps masking/clipping to bounds is one of those things it does differently.

You can try solving your issue a number of ways:

  • make your background transparent:

        layer.backgroundColor = [UIColor clearColor].CGColor;
    
  • clip yourself inside your custom drawRect::

    - (void)drawRect:(CGRect)rect {
        [[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:30.0] addClip];
        [image drawInRect:rect];  // or whatever
    }
    
  • carve out the corners explicitly:

    CGContextBeginPath(c);
    CGContextAddArc(c, r, r, r, M_PI, 3*M_PI_2, 0);
    CGContextAddLineToPoint(c, 0, 0);
    CGContextClosePath(c);
    CGContextClip(c);
    [[UIColor grayColor] setFill];
    UIRectFill(rect);
    

I stole those last 2 suggestions from this great presentation from WWDC 2010: Advanced Performance Optimization on iPhone OS (video listed at this index page -- annoyingly, no direct link).

This is an old question, but I was recently reading a useful blog post titled Abusing UIView. In it the author advises against overriding drawRect to do things like add a border when there are other ways of doing it. He says,

Overriding drawRect: causes a performance hit. I haven’t profiled it, so I don’t know if it’s a signifigant performance under normal circumstances (it’s probably not), but in most cases, folks who override drawRect: can accomplish what they want much easier by setting properties on a view’s layer property. If you need to draw an outline around a view, here’s how you would do it:

#import <QuartzCore/QuartzCore.h>

- (id)initWithFrame:(CGRect)frame {
  self = [super initWithFrame:frame];
  if (self) {
      self.layer.borderWidth = 2.f;
      self.layer.borderColor = [UIColor redColor].CGColor;
  }
  return self;

I realize this probably doesn't solve the problem of the black background showing through. It is just something else to think about.

Setting

opaque = false // NO for ObjC

on the view solves the problem.

Probably you shouldn't call the

[super drawRect:rect]

inside your drawRect. Apple says that:

If you subclass UIView directly, your implementation of this method does not need to call super. However, if you are subclassing a different view class, you should call super at some point in your implementation.

It seems that calling the super method causes strange behaviour.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!