Получение слова, затронутого в UILabel/UITextView

То, что я хотел бы сделать, - создать компонент текстового контейнера, который может указать, что является ближайшим словом, когда есть касание к нему (т.е. слово "позади" затронутой точки).

Сначала я создал подкласс UILabel и переопределил метод touchesEnded: withEvent: для определения затронутого CGPoint. Я также написал метод, который вычисляет соответствующий "кадр" (CGRect) каждого слова текста, используя sizeWithFont: forWidth: lineBreakMode:. С затронутым CGPoint и этим фреймом я могу определить, какое слово на самом деле тронуто. Но метод, который вычисляет фрейм, работает только с текстом монострона.

Итак, теперь мне нужно знать, какая часть текста находится на данной строке (т.е. как текст был разбит), так что я могу определить правильный левый край и верхний край каждого слова.

Любая идея, как я могу это получить? Или, может быть, у вас есть более простое решение для этого? Этот пост, к сожалению, не очень помог......

Ответ 1

(В вашей связанной записи есть ссылка на проект кода кода, который содержит некоторый полезный примерный код, но я также опишу этот процесс для вас здесь.)

Короче говоря, вам понадобится использовать Core Text, который представляет собой усовершенствованную платформу для обработки текста на основе C, которая поддерживает все сложные текстовые макеты в iOS и OS X.

Полный код будет несколько задействован, но ключевые методы, которые вы хотите посмотреть:

CTFramesetterCreateWithAttributedString() - используйте это вместе с NSAttributedString, которое вы получите из текста ярлыка - для создания набора фреймов

CTFramesetterCreateFrame() - используйте это, чтобы получить CTFrameRef для вашего текста из вышеуказанного набора фреймов. Вам нужно будет создать CGPathRef, используя ваши метки для этого.

CTFrameGetLines(), CTFrameGetLineOrigins() - используйте их для получения CTLineRefs, соответствующих строкам набора, и координат начала строки соответственно, затем используйте CTLineGetStringIndexForPosition(), чтобы найти индекс символа в месте касания.

Затем вы можете использовать этот индекс символов (в рамке ссылки на строку) для работы назад и поиска фактического символа/слова/etc в пределах вашей полной строки.

Не забывайте, что вопросы сложны из-за проблем пары:

  • Если вы используете собственный рисунок UILabel, вам придется позаботиться о том, чтобы полностью соответствовать вашим меткам набора, что может быть громоздким, поскольку большинство объектов (например, CTFontRef) не являются бесплатными для мостов с их UIKit-аналогами. Реализация собственного чертежа иногда может быть проще, что гарантирует соответствие показателей.

  • В основном тексте используется инвертированная система координат по отношению к нормальной системе рисования iOS. Если вы получаете дурные результаты, и особенно если вы делаете свой собственный рисунок, это то, на что нужно взглянуть.

Не самая легкая задача в мире, но далека от невозможности. Удачи!

Ответ 2

После небольшого поиска я написал для этого код. Код будет работать для UITextView и UILabel.
Просто скачайте VSWordDetector.zip, затем разархивируйте его и перетащите папку VSWordDetector в свой проект.
Есть два файла VSWordDetector.h и VSWordDetector.m
#import VSWordDetector.h в вашем классе ViewController.

@property (strong, nonatomic) VSWordDetector *wordDetector;

Примечание. Сделать его свойство не так локально.

Теперь он готов для вас, просто добавьте его на textViews или Labels

-(void)viewDidLoad
{
   self.wordDetector = [[VSWordDetector alloc] initWithDelegate:self];
   [self.wordDetector addOnView:textView];
   [self.wordDetector addOnView:label];
}

-(void)wordDetector:(VSWordDetector *)wordDetector detectWord:(NSString *)word
{
   NSLog(@"Detected Word: %@", word);
}

Этот метод делегата будет вызываться, когда вы нажмете на подключенную метку или textView.

EDIT: Пример кода для VSWordDetector.

ПРЕДЛАГАЕМЫЙ РЕДАКТИРОВАНИЕ: Если вы не хотите загружать образец кода, вот код для обоих файлов. См. Этот файл gist VSWordDetector.

Ответ 3

Хотя это старый вопрос, но я подумал, что это может помочь.

Поскольку основной текст был огромным, я выбрал GLTapDemo от German Laullon

С несколькими изменениями это отлично работает для обнаружения затронутого слова на UILabel.