Pergunta

Eu tenho alguns em um manipulador de toque que responde a um toque em uma visão em que desenhei algum texto atribuído. Com isso, eu tenho até o ponto em que tenho um CTRunRef (e a linha associada), bem como o número de glifos nessa execução.

O que não sou capaz de descobrir facilmente, é como posso pegar essa execução de glifos e, dada a minha string atribuída, mapeá -la para os caracteres na string.

Especificamente, o problema é que eu gostaria de saber qual palavra o usuário tocou na visualização, para que eu possa processar se essa palavra é ou não um URL e disparar um método de delegado personalizado para que eu possa abrir uma visualização da Web com ele. Eu tenho todas as substâncias possíveis, simplesmente não sei como mapear onde o usuário bateu em uma substring específica.

Qualquer ajuda seria muito apreciada.

ATUALIZAR: Na verdade, fui e fiz de uma maneira diferente, por sugestão de outra pessoa fora do Stackoverflow. Basicamente, o que fiz é definir um atributo personalizado, @"MyAppLinkAddress" Com o valor do URL, encontrei quando estava convertendo a string em uma string atribuída. Isso acontece antes de eu desenhar a string. Portanto, quando ocorre um evento TAP, eu apenas verifico se esse atributo existe e, se sim, ligue para o método delegado, se não, apenas ignore -o. Está funcionando como eu gostaria agora, mas vou deixar essa pergunta aberta por mais alguns dias, se alguém puder encontrar uma resposta, vou aceitá -la com prazer se for uma solução de trabalho para que alguns outros pode ser capaz de achar essas informações úteis em algum momento no futuro.

Foi útil?

Solução

Então, como mencionei na atualização, optei por seguir uma rota diferente. Em vez disso, tive a ideia de usar um atributo personalizado na sequência atribuída para especificar meu link, já que eu o tive no tempo de criação. Então eu fiz isso. Então, no meu manipulador de toque, quando uma corrida é tocada, verifico se essa execução tem esse atributo e, se sim, ligue para meu delegado com ele. A partir daí, fico feliz carregando uma visão da web com esse URL.

EDITAR: Abaixo estão os trechos de código explicando o que eu fiz nesta resposta. Apreciar.

// 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];

então...

// 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();
        }
}

Outras dicas

Depois de encontrar a linha tocada, você pode pedir o índice em String ligando CTLineGetStringIndexForPosition(). Não há necessidade de acessar corridas individuais.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top