Skip to content

Instantly share code, notes, and snippets.

@siuying
Forked from soffes/NSString+Cheddar.m
Last active August 29, 2015 14:17
Show Gist options
  • Save siuying/680ecf56b99c3da906ee to your computer and use it in GitHub Desktop.
Save siuying/680ecf56b99c3da906ee to your computer and use it in GitHub Desktop.
#import "NSString+UnicodeLength.h"
@implementation NSString (UnicodeLength)
/**
* @param range a unicode codepoint range, as described in twitter
* @return rante a NSRange for the string
* @see https://dev.twitter.com/overview/api/counting-characters
*/
- (NSRange)composedRangeWithRange:(NSRange)range {
__block NSRange adjustedRange = range;
// adjust location
for (NSUInteger i = 0; i < range.location + 1; i++) {
unichar theChar = [self characterAtIndex:i];
if (CFStringIsSurrogateHighCharacter(theChar)) {
adjustedRange.location++;
}
}
// adjust length
__block NSInteger count = 0;
for (NSUInteger i = adjustedRange.location; i < self.length; i++) {
unichar theChar = [self characterAtIndex:i];
if (CFStringIsSurrogateHighCharacter(theChar)) {
adjustedRange.length++;
} else {
// Add one to the count
count++;
// If we have iterated as many times as the original length, stop.
if (range.length == count) {
break;
}
}
}
return adjustedRange;
}
- (NSString *)composedSubstringWithRange:(NSRange)range {
// Return a substring using a composed range so surrogate unicode pairs (composed characters) count as 1 in the
// range instead of however many unichars they actually are.
return [self substringWithRange:[self composedRangeWithRange:range]];
}
@end
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import <Expecta/Expecta.h>
#import "NSString+UnicodeLength.h"
@interface NSStringUnicodeLengthTests : XCTestCase
@end
@implementation NSStringUnicodeLengthTests
- (void)testRangeForComposedCharacterSequencesRangeThai {
// emoji + hashtag
// status_id = 580031725297782784
NSString* input = @"ผมนี่น้ำตาไหลจริงใจกะตอน25มาก 😭 ทำไมพี่เอมไม่ฟังน้ำทำไมต้องทำร้ายจิตใจทำร้ายร่างกายขนาดนั้นด้วย 😭 พี่เอมใจร้าย เกลียดไอ้โอม 😫 #รักของเรา";
NSRange range = NSMakeRange(126, 10);
NSString* substring = [input ig_composedSubstringWithRange:range];
BOOL isEqual = [substring isEqualToString:@"#รักของเรา"];
expect(isEqual).to.beTruthy();
input = @"ผมนี่น้ำตาไหลจริงใจกะตอน25มาก 😭 ทำไมพี่เอมไม่ฟังน้ำทำไมต้องทำร้ายจิตใจทำร้ายร่างกายขนาดนั้นด้วย 😭 พี่เอมใจร้าย เกลียดไอ้โอม 😫 #😭รักของเรา";
range = NSMakeRange(126, 11);
substring = [input ig_composedSubstringWithRange:range];
isEqual = [substring isEqualToString:@"#😭รักของเรา"];
expect(isEqual).to.beTruthy();
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment