I want to determine the writing direction of a string so that I can render Right-to-Left languages such as Arabic correctly in a CALayer.
so I have this method
+(UITextAlignment)alignmentForString:(NSString *)astring
{
UITextView *text = [[UITextView alloc] initWithFrame:CGRectZero];
text.text = astring;
if ([text baseWritingDirectionForPosition:[text beginningOfDocument] inDirection:UITextStorageDirectionForward] == UITextWritingDirectionRightToLeft) {
return UITextAlignmentRight;
}
return UITextAlignmentLeft;
}
Works fine but feels a little heavy just for the purpose of discovering which way to align my text especially as its been called in drawInContext (although relatively infrequently).
Is there a lighter way of determining the writing direction for a given string or should I just stick with this under the basis of premature optimisation. And its got to be iOS 5 friendly.
The code in the question although functional is brutally expensive. Run it through a profiler and you will find that it spends close to 80% of the time in UITextView.setText
when used in the drawInContext method for a layer.
Most of the answer is here in Detect Language of NSString
a better form is thus...
+(UITextAlignment)alignmentForString:(NSString *)astring
{
if (astring.length) {
NSArray *rightLeftLanguages = @[@"ar",@"he"];
NSString *lang = CFBridgingRelease(CFStringTokenizerCopyBestStringLanguage((CFStringRef)astring,CFRangeMake(0,[astring length])));
if ([rightLeftLanguages containsObject:lang]) {
return UITextAlignmentRight;
}
}
return UITextAlignmentLeft;
}
As Arabic and Hebrew are the only Right-to-Left languages detectable by CFStringTokenizerCopyBestStringLanguage
and should also cover Persian, Urdu and Yiddish though I havent tested that.
see also http://en.wikipedia.org/wiki/Right-to-left
For me the .natural
textAlignment
of UITextView
did not work unless I edited the text and line from start.
Based on the great answer to this question and the comment below it.
let text = "..."
let lang = CFStringTokenizerCopyBestStringLanguage(text as CFString, CFRange(location: 0, length: text.characters.count))
if let lang = lang {
let direction = NSLocale.characterDirection(forLanguage: lang as String)
if direction == .rightToLeft {
textView.textAlignment = .right
}
else {
textView.textAlignment = .left
}
}
Since UITextAlignment is deprecated, here's an NSString category with NSWritingDirection:
- (NSWritingDirection)alignment{
if (self.length) {
NSArray *rightLeftLanguages = @[@"ar",@"he"];
NSString *lang = CFBridgingRelease(CFStringTokenizerCopyBestStringLanguage((CFStringRef)self,CFRangeMake(0,self.length)));
if ([rightLeftLanguages containsObject:lang]) {
return NSWritingDirectionRightToLeft;
}
}
return NSWritingDirectionLeftToRight;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With