Skip to content

Emoji freezing my APP on TTTAttributedLabel.m #251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
digabriel opened this issue Jul 31, 2013 · 3 comments
Closed

Emoji freezing my APP on TTTAttributedLabel.m #251

digabriel opened this issue Jul 31, 2013 · 3 comments

Comments

@digabriel
Copy link

Hi. First of all, thanks for TTTAttributedLabel. It is awesome.
I'm having some strange issue when trying to display emoji characters.

For instance, this text
screen shot 2013-07-31 at 11 11 38 am causes the app to freeze on line 312 of the .m file (self.framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)self.renderedAttributedText);)

I run the app using Activity Monitor from Instruments and the CPU load increases to 100% when reaching this point of the code, causing the app freezin. The strange thing is that the app does not crash.

Anyone experiencing the same issue?

Thanks!

@schlu
Copy link

schlu commented Aug 26, 2013

I think I figured this out and have a very small test case.

This Code works:

TTTAttributedLabel *linkLabel = [[TTTAttributedLabel alloc] initWithFrame:CGRectMake(0, 0, 200, 10)];
linkLabel.text = //Any Emoji Character
[linkLabel addLinkToURL:[NSURL URLWithString:@"http://google.com"] withRange:NSMakeRange(0,2)];
[linkLabel sizeToFit];

This code does not:

TTTAttributedLabel *linkLabel = [[TTTAttributedLabel alloc] initWithFrame:CGRectMake(0, 0, 200, 10)];
linkLabel.text = //Any Emoji Character
[linkLabel addLinkToURL:[NSURL URLWithString:@"http://google.com"] withRange:NSMakeRange(0,1)];
[linkLabel sizeToFit];

The difference is that you (and I) are trying to add a link to the middle of a unicode character. So in order to cover the entire emoji character your range needs to be adjusted. For each unicode character you need to add 1 to your length in your range.

I don't think it should just hang, but I suspect this might be a coretext issue, not TTTAttributedLabel issue.

@digabriel
Copy link
Author

@schlu i think that this is exactly what is happen. But i don't think that just add 1 will fix the issue for all unicode characters.

Some unicode characters are called "Composed characters" and can have a length higher the 1. So, in other sections of my app, i'm using this custom category method (of NSString) to calculate the correct length of a string:

-(NSUInteger)numberOfComposedCharacterSequences{
    __block NSUInteger count = 0;
    [self enumerateSubstringsInRange:NSMakeRange(0, self.length)
                             options:NSStringEnumerationByComposedCharacterSequences
                          usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop){
                              count++;
                          }];
    return count;
}

You could try this out on your code. I'm not using more TTTAttributedLabel :)
If you confirm that this solves the issue, i think that this issue can be closed.

@schlu
Copy link

schlu commented Aug 27, 2013

Right, I misspoke when I said "unicode" characters. I really meant something else.

I am not sure what you would do with your method.

When I run it on the string @"asdf" I get a count of 4. When I run it on any single emoji character I get 1.

I am also doing linking in the middle strings. So the total number of composed characters isn't that helpful.

Your tip about composed characters was incredible for me though. I wrote a function that takes a range the server is providing and converts it to the range that I need to provide for the link in the label. I am sure there is a better name for this category method on NSString. I should note that this is a very inefficient method if you have long strings, my strings are limited to < 100 characters or so and it seems fine.

- (NSRange)stringRangeInComposedCharactersRange:(NSRange)composedCharactersRange {
    __block int composedCount = 0;
    [self enumerateSubstringsInRange:NSMakeRange(0, self.length)
                             options:NSStringEnumerationByComposedCharacterSequences
                          usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop){
                              composedCount++;
                          }];
    if (self.length == composedCount) {
        return composedCharactersRange;
    } else {
        NSMutableString *composedCharacterString = [NSMutableString string];
        __block int currentComposedCount = 0;
        [self enumerateSubstringsInRange:NSMakeRange(0, self.length)
                                 options:NSStringEnumerationByComposedCharacterSequences
                              usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop){
                                  if (currentComposedCount >= composedCharactersRange.location &&
                                      currentComposedCount < composedCharactersRange.location + composedCharactersRange.length) {
                                      [composedCharacterString appendString:[self substringWithRange:substringRange]];
                                  }
                                  currentComposedCount++;
                              }];
        return [self rangeOfString:composedCharacterString];
    }
}

I am fine closing this issue. I don't think it is an issue in the library. And there is a work around.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants