Search code examples
iosobjective-cuiviewcore-graphics

Erasing text from a drawn UIView


I'm trying to draw a UIView and erase text from it to produce an effect similar to this:

enter image description here

So far, I've not been able to figure out a way to get the text to act as an eraser. This is where I'm at:

enter image description here

CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(c, [UIColor whiteColor].CGColor);
CGContextFillRect(c, self.bounds);
CGContextSetBlendMode(c, kCGBlendModeClear);
CGContextSetTextDrawingMode(c, kCGTextFill);
CGContextSetFont(c, CGFontCreateWithFontName(CFStringCreateWithCString(NULL, "HelveticaNeue-Bold", kCFStringEncodingUTF8)));
CGContextSetFontSize(c, 18.0);
UIGraphicsPushContext(c);
[_text drawInRect:self.bounds
   withAttributes:nil];
UIGraphicsPopContext();

I was hoping that CGContextSetBlendMode(c, kCGBlendModeClear); would make the text act as an eraser, but so far, I've had no luck.

I also had the idea to use a UILabel as a maskView, but I don't know how to invert it so that the text is treated as negative space. The only questions I've been able to find on inverting masks are inverting CAShapeLayers or UIImages.


Solution

  • I noticed you're using the word eraser. In the design world this sort of effect would be known as a mask. The mask will hide portions of the layer revealing whatever is below.

    You can do this using a label and a view like so:

    let view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
    let label = UILabel(frame: view.frame)
    label.text = "$48.99"
    label.font = UIFont.systemFont(ofSize: 70)
    label.textAlignment = .center
    label.textColor = UIColor.white
    
    let underlyingView = UIView(frame: view.frame)
    underlyingView.backgroundColor = UIColor.blue
    underlyingView.mask = label
    
    view.addSubview(underlyingView)