5

TTTAttributedLabel を使用してテキストに書式を適用していますが、絵文字を含む範囲に書式を適用しようとしているため、クラッシュするようです。例:

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

注: API から NSRange 値とテキスト文字列が渡されます。

上記では、#hashtag にフォーマットを適用しようとしています。通常はこれで問題なく動作しますが、文字列に絵文字が含まれているため、識別された範囲が絵文字をフォーマットしようとしていると考えられます。これらは実際には UTF 値であり、TTTAttributedLabel でクラッシュを引き起こします (実際にはクラッシュせずにハングしますが、. ..)

不思議なことに、絵文字が 1 つあれば問題なく動作しますが、2 つあると壊れます。

ここで何をすべきかを理解するのを手伝ってくれる人はいますか?

4

2 に答える 2

3

問題は、\U10000 以上の Unicode 値を持つ文字列内の Unicode 文字が、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];
}
于 2013-03-09T16:18:00.807 に答える
2

これは Twitter API によるもので、返されるエンティティ ディクショナリを使用しようとしていると思います。NSString文字列の範囲のバージョンとともに、これらの範囲の処理をサポートするコードを書いています。

私のアプローチは、余分な文字に対処するために Twitter が返すエンティティ ディクショナリを「修正」することでした。さまざまな理由でコードを共有することはできませんが、これが私がしたことです:

  1. エンティティ ディクショナリの変更可能なディープ コピーを作成します。
  2. これを行うこと unicharにより、文字列の範囲全体をループします。unichar
    1. unicharがサロゲート ペアの範囲 ( 0xd800-> ) 内にあるかどうかを確認し0xdfffます。
    2. サロゲート ペア コードポイントの場合、エンティティ ディクショナリ内のすべてのエントリを調べて、インデックスが文字列内の現在の位置 (s に関して) より大きい場合は、インデックスを 1 シフトしますunichar。次に、ループ カウンターを 1 増やして、このサロゲート ペアのパートナーをスキップします。
    3. サロゲート ペアでない場合は、何もしません。
  3. すべてのエンティティをループして、文字列の末尾をオーバーランするエンティティがないことを確認します。すべきではありませんが、念のためです。Twitter がダフ データを返すケースがいくつか見つかりました。

それが役立つことを願っています!また、いつの日かこのコードをオープン ソース化できることを願っています。非常に役立つと思います。

于 2013-03-09T16:52:35.220 に答える