2013-03-09 4 views
4

Я использую TTTAttributedLabel, чтобы применить форматирование к тексту, но, похоже, он разбился, потому что я пытаюсь применить форматирование к диапазону, который включает emoji. Пример:Текстовая строка с EMOJI, вызывающая проблемы с NSRange

NSString *text = @"@user1234 #hashtag"; // text.length reported as 22 by NSLog as each emoji is 2 chars in length 
cell.textLabel.text = text; 

int length = 8; 
int start = 13; 

NSRange *range = NSMakeRange(start, length); 

if (!NSEqualRanges(range, NSMakeRange(NSNotFound, 0))) { 
    // apply formatting to TTTAttributedLabel 
    [cell.textLabel addLinkToURL:[NSURL URLWithString:[NSString stringWithFormat:@"someaction://hashtag/%@", [cell.textLabel.text substringWithRange:range]]] withRange:range]; 
} 

Примечание: Я передал значения NSRange из API, а также текстовую строку.

В приведенном выше примере я пытаюсь применить форматирование к #hashtag. Обычно это работает нормально, но поскольку у меня есть emoji, участвующий в этой строке, я считаю, что выбранный диапазон пытается отформатировать emoji, поскольку они на самом деле являются значениями UTF, которые в TTTAttributedLabel приводят к сбою (он фактически зависает без сбоев, но. ..)

Как ни странно, это работает отлично, если есть 1 смайликов, но перерывы, если есть 2.

Может кто-нибудь помочь мне понять, что здесь делать?

+1

Это было бы легче диагностировать, если бы вы указали код, который используете для применения форматирования, и конкретно, какая строка кода «зависает». Ни один из приведенных здесь кодов не ссылается на всю строку. В идеале вы должны иметь возможность создать очень короткую программу, которая демонстрирует проблему, чтобы другие могли ее воспроизвести. –

+0

, добавленный выше, чтобы показать мне применение с использованием метода TTTAttributedLabel addLinkToUrl – mootymoots

ответ

1

Я предполагаю, что это из API Twitter, и вы пытаетесь использовать словарь объектов, который они возвращают. Я только что написал код для поддержки этих диапазонов вместе с версией NSString диапазона строк.

Мой подход состоял в том, чтобы «исправить» словарь сущностей, который Twitter возвращает, чтобы справиться с дополнительными символами. Я не могу поделиться кодом по разным причинам, но это то, что я сделал:

  1. Сделайте глубокую изменяемую копию словарных сущностей.
  2. Петля через весь диапазон строки, unichar по unichar, делая это:
    1. Проверьте, если unichar находится в суррогатной диапазоне пары (0xd800 ->0xdfff).
    2. Если это суррогатная пара codepoint, то просмотрите все записи в словаре объектов и сдвиньте индексы на 1, если они больше, чем текущее местоположение в строке (в терминах unichar s). Затем увеличьте счетчик циклов на 1, чтобы пропустить партнера этой суррогатной пары, как это было обработано сейчас.
    3. Если это не суррогатная пара, ничего не делайте.
  3. Прокрутите все объекты и убедитесь, что ни один из них не наполнит конец строки. Они не должны, а просто распирать. Я нашел некоторые случаи, когда Twitter возвращал данные Duff.

Надеюсь, что это поможет! Я также надеюсь, что однажды я смогу открыть исходный код этого кода, поскольку я думаю, что это было бы невероятно полезно!

+0

На самом деле я попробовал это, но нашел еще более простое решение. Я не использую twitter btw, но похожую на сущности. Каждый объект имеет текст для объекта, поэтому я просто искал диапазон объекта entity.text в полной строке и BINGO, больше никаких проблем. :) – mootymoots

+0

О, отлично, это прекрасно, тогда :-). Хотя я думаю, что если у вас есть 2 объекта с одним и тем же текстом, но ссылки на разные места. Тем не менее, рад, что вы решили! – mattjgalloway

3

Проблема заключается в том, что любой символ Юникода в вашей строке с индексом Unicode \ U10000 или выше будет отображаться как два символа в NSString.

Поскольку вы хотите отформатировать хэштег, вы должны использовать более динамичные способы получения значений начала и длины. Используйте NSString rangeOfString, чтобы найти расположение знака #. Используйте эти результаты и длину строки, чтобы получить необходимую длину.

NSString *text = @"@user1234 #hashtag"; // text.length reported as 22 by NSLog as each emoji is 2 chars in length 
cell.textLabel.text = text; 

NSUInteger start = [text rangeOfString:@"#"]; 
if (start != NSNotFound) { 
    NSUInteger length = text.length - start; 
    NSRange *range = NSMakeRange(start, length); 
    // apply formatting to TTTAttributedLabel 
    [cell.textLabel addLinkToURL:[NSURL URLWithString:[NSString stringWithFormat:@"someaction://hashtag/%@", [cell.textLabel.text substringWithRange:range]]] withRange:range]; 
} 
+1

, который работает, если есть один хэштег, но может быть много, и это будет соответствовать не хэштегам. Я бы предпочел использовать предоставленный диапазон и настроить его на основе emoji. – mootymoots

+2

Правильный подход заключается в сканировании строки для хэштегов. Если строка может содержать более одного хэштага, вы не можете жестко кодировать позиции. Вы должны сканировать строку для хэштегов. Правильно используйте методы 'NSString rangeOfStringXXX', чтобы найти их все. Я просто дал вам пример для поиска. Это легко обновляется, используя цикл, чтобы найти каждый хэштег. Очевидно, что определение длины больше связано с тем, что просто подходит к концу строки. – rmaddy

+0

Я добавил примечание выше, кажется, только проблема, если есть две эмои вместе, она отлично работает, если есть один эмози. – mootymoots