Pregunta

Tengo algunos en un controlador táctil que responde a un grifo en una vista que he dibujado un texto atribuido. A través de esto, tengo hasta el punto en que tengo una CTRunRef (y la línea asociada) como así como el número de glifos en ese plazo.

Lo que yo no soy capaz de averiguar con facilidad, es la forma en que puedo tomar esa racha de glifos y, dada mi cadena con atributos, asignarla a caracteres de la cadena.

En concreto, el problema es que me gustaría saber qué palabra que el usuario dio un golpecito en la vista, por lo que puede procesar independientemente de si esa palabra es una URL y disparar un método delegado personalizada para que pueda abrir una vista web con él . Tengo todos los posibles subseries, simplemente no sé cómo asignar donde el usuario designado para una subcadena en particular.

Cualquier ayuda sería muy apreciada.

Actualizar : De hecho, he ido y lo ha hecho de una manera diferente, por sugerencia de otra persona fuera de stackoverflow. Básicamente lo que he hecho es establecer un atributo personalizado, @"MyAppLinkAddress" con el valor de la dirección URL que se encontró cuando estaba en la conversión de la cadena en una cadena con atributos. Esto sucede antes de que dibujo la cadena. Por lo tanto, cuando se produce un evento del grifo, acabo de comprobar si existe ese atributo, y si es así, llame a mi método de delegado, si no, simplemente lo ignoran. Se está trabajando cómo me gustaría ahora, pero voy a dejar esta cuestión abierta durante unos días más, si alguien puede llegar a una respuesta, voy felizmente acepto si es una solución de trabajo de manera que algunos otros puede ser capaz de encontrar esta información útil en algún momento en el futuro.

¿Fue útil?

Solución

Así que como he mencionado en la actualización, me elegidos para ir una ruta diferente. En lugar de eso tuvo la idea de utilizar un atributo personalizado en la cadena con atributos para especificar mi enlace, ya que lo tenía en el momento de la creación de todos modos. Así que lo hice. Luego, en mi manejador de contacto, cuando se pulsa una carrera, puedo comprobar si tiene que correr ese atributo, y si es así, llamar a mi delegado con él. A partir de ahí estoy feliz de cargar una vista web con esa URL.

Editar : A continuación se presentan 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();
        }
}

Otros consejos

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top