1. How to set fillet to trigger off screen rendering
We often see that rounded corners trigger off screen rendering. But in fact, this statement is not accurate, because rounded corners trigger off screen rendering is also conditional!
Let’s take a look at the description of CornerRadius in Apple’s official documents:
Setting the radius to a value greater than 0.0 causes the layer to begin drawing rounded corners on its background. By default, the corner radius does not apply to the image in the layer’s contents property; it applies only to the background color and border of the layer. However, setting the masksToBounds property to true causes the content to be clipped to the rounded corners.
We found the settingscornerRadius
When it is greater than 0, it is only the of layerbackgroundColor
andborder
Set fillet; Not to the layercontents
Set the fillet unless it is also setlayer.masksToBounds
bytrue
(corresponding to uiview)clipsToBounds
Properties).
If at this time, you thinklayer.masksToBounds
perhapsclipsToBounds
Set totrue
It triggers off screen rendering, which is not entirely correct.
Let’s first open the off screen rendering color mark of the simulator:

- Do not set layer Maskstobounds or clipstobonds. The default value is No
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)];
//Set background color
view1.backgroundColor = UIColor.redColor;
//Set border width and color
view1.layer.borderWidth = 2.0;
view1.layer.borderColor = UIColor.blackColor.CGColor;
//Set fillet
view1.layer.cornerRadius = 100.0;
view1.center = self.view.center;
[self.view addSubview:view1];
}

When we see only the background color, border and fillet, off screen rendering will not be triggered.
- set up
layer.masksToBounds
perhapsclipsToBounds
byYES
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)];
//Set background color
view1.backgroundColor = UIColor.redColor;
//Set border width and color
view1.layer.borderWidth = 2.0;
view1.layer.borderColor = UIColor.blackColor.CGColor;
//Set fillet
view1.layer.cornerRadius = 100.0;
//Set crop
view1.clipsToBounds = YES;
view1.center = self.view.center;
[self.view addSubview:view1];
}

When we openlayer.masksToBounds
perhapsclipsToBounds
The same does not trigger off screen rendering. This is because we haven’t set up the picture yet.
- set up
layer.masksToBounds
perhapsclipsToBounds
byYES
, and set the picture at the same time
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)];
//Set background color
view1.backgroundColor = UIColor.redColor;
//Set border width and color
view1.layer.borderWidth = 2.0;
view1.layer.borderColor = UIColor.blackColor.CGColor;
//Set picture
view1.layer.contents = (__bridge id)[UIImage imageNamed:@"pkq"].CGImage;
//Set fillet
view1.layer.cornerRadius = 100.0;
//Set crop
view1.clipsToBounds = YES;
view1.center = self.view.center;
[self.view addSubview:view1];
}

When we openlayer.masksToBounds
perhapsclipsToBounds
When the picture is set at the same time, off screen rendering will be triggered.
-
In fact, it’s not just pictures. Adding a sub view with image information such as color, content or border to the view will also trigger off screen rendering.
There is image informationIt also includes drawing in the drawing method of view or layer.
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)];
//Set background color
view1.backgroundColor = UIColor.redColor;
//Set border width and color
view1.layer.borderWidth = 2.0;
view1.layer.borderColor = UIColor.blackColor.CGColor;
//Set fillet
view1.layer.cornerRadius = 100.0;
//Set crop
view1.clipsToBounds = YES;
//Subview
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100.0, 100.0)];
//Any of the following three properties
//Set background color
view2.backgroundColor = UIColor.blueColor;
//Set content
view2.layer.contents = (__bridge id)([UIImage imageNamed:@"pkq"].CGImage);
//Set border
view2.layer.borderWidth = 2.0;
view2.layer.borderColor = UIColor.blackColor.CGColor;
[view1 addSubview:view2];
view1.center = self.view.center;
[self.view addSubview:view1];
}

2. The real reason for off screen rendering triggered by fillet
The overlay drawing of layers probably follows the “painter’s algorithm”.
Oil painting algorithm: draw the objects far away from the observer in the scene first, and then draw the objects close to the observer.
First draw the red part, then draw the ⻩ color part, and finally draw the gray ⾊ part to solve the problem of hidden surface elimination. That is, the scene is sorted according to the physical distance and the distance of the observer, and can be drawn from far to near.

When we setcornerRadius
as well asmasksToBounds
When fillet + clipping,masksToBounds
Crop attributes are applied to all layers.

Originally, we drew from back to front. After drawing a layer, we can discard it. But now you need toOffscreen BufferSave in and wait for fillet + clipping, which raises theoffscreen rendering 。
-
Background color, border, background color + border, plus fillet + clipping, according to the document description, becausecontents = nilThere is nothing to crop, so
masksToBounds
Set toYES
perhapsNO
No effect. -
Once weContent is set for contents, whether it is pictures, drawing contents, sub views with image information, etc., plus fillet + clipping, off screen rendering will be triggered.
It is not necessary to directly assign values to contents!
3. Ios9 and subsequent optimization
For fillet, IOS 9 and later system versions, Apple has made some optimizations.
-
layer.contents
/imageView.image
We only set
contents
perhapsUIImageView
ofimage
With rounded corners and clipping, off screen rendering will not occur. However, if you add background color, border or other layers with image content, it will still produce off screen rendering.- (void)viewDidLoad { [super viewDidLoad]; UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)]; //Set picture view1.layer.contents = (__bridge id)[UIImage imageNamed:@"qiyu"].CGImage; //Set fillet view1.layer.cornerRadius = 100.0; //Set crop view1.clipsToBounds = YES; view1.center = self.view.center; [self.view addSubview:view1]; }

In fact, this is understandable, because onlymonolayerThe content needs to be rounded and trimmed, so off screen rendering technology is not required. However, if you add a background color, border or other layer with image content, it will be generated asmulti-storeyAdd fillets and cuts, so off screen rendering will still be triggered (as in the third example in 1).
So we’re using something likeUIButton
You should pay attention to:
-
UIButton
- (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; //Create a button view UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200.0, 200.0)]; //Set picture [button setImage:[UIImage imageNamed:@"pkq"] forState:UIControlStateNormal]; button.center = self.view.center; [self.view addSubview:button]; }
We are
UIButton
Setting a picture actually adds oneUIImageView
。

-
by
UIButton
Adding fillets and clipping triggers off screen rendering.//Set fillet button.layer.cornerRadius = 100.0; //Set crop button.clipsToBounds = YES;

-
If changed to
UIButton
MediumUIImageView
Add fillets and clipping, thenOff screen rendering is not triggered。//Set fillet button.imageView.layer.cornerRadius = 100.0; //Set crop button.imageView.clipsToBounds = YES;

So we can simply set the fillet
imageView.clipsToBounds = YES;
imageView.layer.cornerRadius = 19.0;