Для UILabel
, я хотел бы узнать, какой индекс символа находится в определенной точке, полученной от события касания. Я хотел бы решить эту проблему для iOS 7 с помощью текстового набора.
Так как UILabel не предоставляет доступ к его NSLayoutManager
, я создал свой собственный на основе конфигурации UILabel
следующим образом:
- (void)textTapped:(UITapGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateEnded) {
CGPoint location = [recognizer locationInView:self];
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:self.attributedText];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:self.bounds.size];
[layoutManager addTextContainer:textContainer];
textContainer.maximumNumberOfLines = self.numberOfLines;
textContainer.lineBreakMode = self.lineBreakMode;
NSUInteger characterIndex = [layoutManager characterIndexForPoint:location
inTextContainer:textContainer
fractionOfDistanceBetweenInsertionPoints:NULL];
if (characterIndex < textStorage.length) {
NSRange range = NSMakeRange(characterIndex, 1);
NSString *value = [self.text substringWithRange:range];
NSLog(@"%@, %zd, %zd", value, range.location, range.length);
}
}
}
Код выше находится в подклассе UILabel
с UITapGestureRecognizer
, настроенным на вызов textTapped:
(Gist).
Получающийся индекс символа имеет смысл (увеличивается при нажатии слева направо), но неверен (последний символ достигнут примерно в половине ширины метки). Похоже, что размер шрифта или размер текстового контейнера не настроен должным образом, но не может найти проблему.
Мне бы хотелось, чтобы мой класс был подклассом UILabel
вместо использования UITextView
. Кто-нибудь решил эту проблему для UILabel
?
Обновление: Я потратил билет DTS на этот вопрос, и инженер Apple рекомендовал переопределить UILabel
drawTextInRect:
с реализацией, которая использует мой собственный менеджер макетов, подобный этому фрагменту кода:
- (void)drawTextInRect:(CGRect)rect
{
[yourLayoutManager drawGlyphsForGlyphRange:NSMakeRange(0, yourTextStorage.length) atPoint:CGPointMake(0, 0)];
}
Я думаю, что было бы очень сложно сохранить мой собственный менеджер макетов синхронно с настройками ярлыков, поэтому я, вероятно, поеду с UITextView
, несмотря на мое предпочтение UILabel
.
Обновление 2: Я решил использовать UITextView
в конце концов. Цель всего этого заключалась в обнаружении ответвлений ссылок, встроенных в текст. Я попытался использовать NSLinkAttributeName
, но эта установка не вызывала обратный вызов делегата при быстром нажатии ссылки. Вместо этого вам нужно нажать ссылку на определенное время - очень раздражает. Поэтому я создал CCHLinkTextView, у которого нет этой проблемы.