2010-09-29 13 views
9

Tengo algunos en un controlador táctil que responde a un toque en una vista que he dibujado algún texto atribuido. A través de esto, llegué al punto en que tengo un CTRunRef (y el asociado línea), así como el número de glifos en esa ejecución.Caracteres de mapeo CoreText

Lo que no puedo descifrar fácilmente, es cómo puedo tomar esa serie de glifos y, dada la cadena atribuida, asignarla a los caracteres de la cadena.

Específicamente el problema es que me gustaría saber qué palabra utilizó el usuario en la vista, así que puedo procesar si esa palabra es una URL y activar un método de delegado personalizado para poder abrir una vista web con eso. Tengo todas las subseries posibles, simplemente no sé cómo mapear donde el usuario tocó una subcadena en particular.

Cualquier ayuda sería muy apreciada.

ACTUALIZACIÓN: De hecho, me he ido y lo he hecho de otra manera, por sugerencia de otra persona fuera de stackoverflow. Básicamente lo que hice fue establecer un atributo personalizado, @"MyAppLinkAddress" con el valor de la URL que encontré cuando convertía la cadena en una cadena atribuida. Esto sucede antes de dibujar la cadena. Por lo tanto, cuando ocurre un evento tap, simplemente compruebo si ese atributo existe, y si es así, llamo a mi método delegado, si no, simplemente ignórelo. Está funcionando como me gustaría ahora, pero voy a dejar esta pregunta abierta por unos días más, si alguien puede encontrar una respuesta, lo aceptaré felizmente si es una solución funcional para que otros puede ser capaz de encontrar esta información útil en algún momento en el futuro.

Respuesta

7

Así como mencioné en la actualización, elegí hacer una ruta diferente. En su lugar, tuve la idea de usar un atributo personalizado en la cadena atribuida para especificar mi enlace, ya que lo tenía en el momento de la creación de todos modos. Así que hice eso. Luego, en mi controlador táctil, cuando se toca una ejecución, compruebo si esa ejecución tiene ese atributo y, de ser así, llamo a mi delegado. A partir de ahí, estoy felizmente cargando una vista web con esa URL.

EDIT: A continuación hay fragmentos de código que explican lo que hice en esta respuesta. Disfrutar.

// When creating the attribute on your text store. Assumes you have the URL already. 
// Filled in for convenience 
NSRange urlRange = [tmpString rangeOfString:@"http://www.foo.com/"]; 
[self.textStore addAttribute:(NSString*)kCTForegroundColorAttributeName value:(id)[UIColor blueColor].CGColor range:urlRange]; 
[self.textStore addAttribute:@"CustomLinkAddress" value:urlString range:urlRange]; 

entonces ...

// Touch handling code — Uses gesture recognizers, not old school touch handling. 
// This is just a dump of code actually in use, read through it, ask questions if you 
// don't understand it. I'll do my best to put it in context. 
- (void)receivedTap:(UITapGestureRecognizer*)tapRecognizer 
{ 
     CGPoint point = [tapRecognizer locationInView:self]; 

     if(CGRectContainsPoint(textRect, point)) 
     { 
       CGContextRef context = UIGraphicsGetCurrentContext(); 

       point.y = CGRectGetHeight(self.contentView.bounds) - kCellNameLabelHeight - point.y; 

       CFArrayRef lines = CTFrameGetLines(ctframe); 
       CFIndex lineCount = CFArrayGetCount(lines); 
       CGPoint origins[lineCount]; 
       CTFrameGetLineOrigins(ctframe, CFRangeMake(0, 0), origins); 
       for(CFIndex idx = 0; idx < lineCount; idx++) 
       { 
         CTLineRef line = CFArrayGetValueAtIndex(lines, idx); 
         CGRect lineBounds = CTLineGetImageBounds(line, context); 
         lineBounds.origin.y += origins[idx].y; 

         if(CGRectContainsPoint(lineBounds, point)) 
         { 
           CFArrayRef runs = CTLineGetGlyphRuns(line); 
           for(CFIndex j = 0; j < CFArrayGetCount(runs); j++) 
           { 
             CTRunRef run = CFArrayGetValueAtIndex(runs, j); 
             NSDictionary* attributes = (NSDictionary*)CTRunGetAttributes(run); 
             NSString* urlString = [attributes objectForKey:@"CustomLinkAddress"]; 
             if(urlString && ![urlString isEqualToString:@""]) 
             { 
               [self.delegate didReceiveURL:[NSURL URLWithString:urlString]]; 
               UIGraphicsPopContext(); 
               return; 
             } 
           } 
         } 
       } 
       UIGraphicsPopContext(); 
     } 
} 
+0

No necesita llamar 'UIGraphicsPopContext()' aquí. Estás obteniendo el contexto, no empujando uno nuevo. – mohsenr

3

Después de encontrar la línea aprovechado, puede solicitar el índice en cadena llamando CTLineGetStringIndexForPosition(). No es necesario acceder a ejecuciones individuales.