Subclase UIView de iOS, dibujar texto transparente a fondo

Quiero dibujar texto en mi subclase en UIView para que el texto se recorte de la forma y se vea el fondo detrás de la vista, al igual que en el logotipo de OSX Mavericks que se encuentra aquí .

Diría que soy más un desarrollador de iOS intermedio / avanzado, así que no dudes en lanzarme algunas soluciones locas. Esperaría que tuviera que anular drawRect para hacer esto.

¡Gracias chicos!

EDITAR:

Debo mencionar que mi primer bash fue hacer que el texto [UIColor clearColor] no funcionara, ya que solo establecía el componente alfa del texto en 0, que solo mostraba la vista a través del texto.

Descargo de responsabilidad: Estoy escribiendo esto sin pruebas, así que perdónenme si me equivoco aquí.

Debería lograr lo que necesita con estos dos pasos:

  1. Cree un CATextLayer con el tamaño de su vista, configure el backgroundColor para que sea completamente transparente y foregroundColor sea ​​opaco (por [UIColor colorWithWhite:0 alpha:1] y [UIColor colorWithWhite:0 alpha:0] . Luego configure la propiedad de string para la cadena que desea representar, font y fontSize font , etc.

  2. Establezca la máscara de la capa de su vista en esta capa: myView.layer.mask = textLayer . Tendrá que importar QuartzCore para acceder al CALayer de su vista.

Tenga en cuenta que es posible que cambie entre el color opaco y el transparente en el primer paso.

Editar: De hecho, Noah tenía razón. Para superar esto, utilicé CoreGraphics con el modo de fusión kCGBlendModeDestinationOut .

Primero, una vista de muestra que muestra que efectivamente funciona:

 @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 

Después de agregar esto a su controlador de vista, verá la vista detrás de TestView donde Hello! es dibujado.

Por qué funciona esto:

El modo de fusión se define como R = D*(1 - Sa) , lo que significa que necesitamos valores alfa opuestos que en la capa de mask que sugerí antes. Por lo tanto, todo lo que necesita hacer es dibujar con un color opaco y esto se restará de las cosas que dibujó en la vista de antemano.

De hecho, me di cuenta de cómo hacerlo por mi cuenta, sorprendentemente, pero la respuesta de @ StatusReport es completamente válida y funciona tal como está ahora.

Así es como lo hice:

 -(void)drawRect:(CGRect)rect{ CGContextRef context = UIGraphicsGetCurrentContext(); [[UIColor darkGrayColor]setFill]; //this becomes the color of the alpha mask CGContextFillRect(context, rect); CGContextSaveState(context); [[UIColor whiteColor]setFill]; //Have to flip the context since core graphics is done in cartesian coordinates CGContextTranslateCTM(context, 0, rect.size.height); CGContextScaleCTM(context, 1.0, -1.0); [textToDraw drawInRect:rect withFont:[UIFont fontWithName:@"HelveticaNeue-Thin" size:40]; CGContextRestoreGState(context); CGImageRef alphaMask = CGBitmapContextCreateImage(context); [[UIColor whiteColor]setFill]; CGContextFillRect(context, rect); CGContextSaveGState(context); CGContentClipToMask(context, rect, alphaMask); [backgroundImage drawInRect:rect]; CGContextRestoreGState(context); CGImageRelease(alphaMask); } - (void)setTextToDraw:(NSString*)text{ if(text != textToDraw){ textToDraw = text; [self setNeedsDisplay]; } } 

Tengo una statement @synthesize para textToDraw para poder anular el setter y llamar a [self setNeedsDisplay] . No estoy seguro de si eso es totalmente necesario o no.

Estoy seguro de que esto tiene algunos errores tipográficos, pero te puedo asegurar que la versión corregida funciona correctamente.