Символы сопоставления Coretext
Вопрос
У меня есть некоторые в сенсорном обработке, который реагирует на кран на мнение, что я нарисовал некоторые приписанные текст. Через это я дошел до такой степени, что у меня есть CTRunRef
(и связанная линия), а также количество глифов в этом запуске.
То, что я не могу выяснить легко, это то, как я могу взять этот пробег глифов и, учитывая мою приписанную строку, сопоставьте ее символам в строке.
В частности, проблема в том, что я хотел бы знать, какое слово пользователь включен в поле зрения, поэтому я могу обрабатывать, следует ли это слово URL-адрес и устрелить метод пользовательского делегата, поэтому я могу открыть вид с ним. У меня есть все возможные подстроки, я просто не знаю, как отобратьте, где пользователь постучал в определенную подстроку.
Любая помощь будет очень ценится.
ОБНОВИТЬ: Я на самом деле ушел и сделал это по-другому, по предложению другого человека от стека. В основном то, что я сделал, это установить пользовательский атрибут, @"MyAppLinkAddress"
С ценностью URL я нашел, когда я преобразую строку в приписанную строку. Это происходит до того, как я нарисую строку. Следовательно, когда происходит событие Tap, я просто проверяю, существует ли этот атрибут, и если это так, позвоните моим методом делегата, если нет, просто игнорируйте его. Это работает, как я бы хотел, но я собираюсь оставить этот вопрос открытым в течение нескольких дней, если кто-то может придумать ответ, я счастливо приму это, если это рабочее решение, так что некоторые другие Может быть в состоянии найти эту информацию полезной в какой-то момент в будущем.
Решение
Так как я упоминал в обновлении, я решил пойти по другому маршруту. Вместо этого я получил идею использовать пользовательский атрибут в приписанной строке, чтобы указать мою ссылку, поскольку у меня все равно было его во время создания. Так что я сделал это. Затем в моем сенсорном обработке, когда запустится, я проверяю, имеет ли этот run этот атрибут, и если это так, вызовите мой делегат с ним. Оттуда я счастливо загружаю веб-просмотр с этим URL.
РЕДАКТИРОВАТЬ: Ниже приведены фрагменты кода, объясняющими, что я сделал в этом ответе. Наслаждаться.
// 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];
потом...
// 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();
}
}
Другие советы
После того, как вы найдете спущенную линию, вы можете попросить индекс в строке, позвонив CTLineGetStringIndexForPosition()
. Отказ Там нет необходимости получать доступ к индивидуальным бегам.