Disclaimer: I'm writing this without testing, so forgive me if I'm wrong here.
You should achieve what you need by these two steps:
Create a CATextLayer
with the size of your view, set the backgroundColor
to be fully transparent and foregroundColor
to be opaque (by [UIColor colorWithWhite:0 alpha:1]
and [UIColor colorWithWhite:0 alpha:0]
. Then set the string
property to the string you want to render, font
and fontSize
etc.
Set your view's layer's mask to this layer: myView.layer.mask = textLayer
. You'll have to import QuartzCore
to access the CALayer
of your view.
Note that it's possible that I switched between the opaque and transparent color in the first step.
Edit: Indeed, Noah was right. To overcome this, I used CoreGraphics with the kCGBlendModeDestinationOut
blend mode.
First, a sample view that shows that it indeed works:
@implementation TestView
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor clearColor];
}
return self;
}
- (void)drawRect:(CGRect)rect {
[[UIColor redColor] setFill];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:10];
[path fill];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context); {
CGContextSetBlendMode(context, kCGBlendModeDestinationOut);
[@"Hello!" drawAtPoint:CGPointZero withFont:[UIFont systemFontOfSize:24]];
} CGContextRestoreGState(context);
}
@end
After adding this to your view controller, you'll see the view behind TestView
where Hello!
is drawn.
Why does this work:
The blend mode is defined as R = D*(1 - Sa)
, meaning we need opposite alpha values than in the mask
layer I suggested earlier. Therefore, all you need to do is to draw with an opaque color and this will be subtracted from the stuff you've drawn on the view beforehand.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…