如何在NSString中反转(颠倒)文本

时间:2014-03-02 15:53:12

标签: objective-c ios7 nsstring uitextview core-text

如何在iOS7中反转NSString变量中的文本? (我想颠倒显示文字)。 注意:有许多解决方案,其中UILabel或UITextView被颠倒翻转,但这不是我想要的。

目前我可以在一个反转字符串的类别中执行以下操作:

+ (NSString *)stringByReversingString:(NSString *)str
{
char cString[150];
char revString[150];
NSString *retval;
[str getCString:cString
      maxLength:[str lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1
       encoding:NSUTF8StringEncoding];

for (int i = 0; i < strlen(cString); i++) {
    revString[i] = cString[strlen(cString) - (i + 1)];
}
revString[strlen(cString)] = '\0';
retval = [NSString stringWithCString:revString encoding:NSUTF8StringEncoding];

return retval;
}

但我怎么会把文字翻过来呢?

2 个答案:

答案 0 :(得分:4)

不能显示一个字符串颠倒的纯字符串转换,你有 翻转包含字符串的视图。

某些 Unicode字符是“普通”字母的倒置版本, 比如

Ⅎ - TURNED CAPITAL F (U+2132)

但不适用于所有角色。 您只能使用http://www.fileformat.info/convert/text/upside-down-map.htm这样的表模仿翻转:

uʍop-ǝpısdn sı ɹoʇıuoɯ ɹnoʎ uǝɥʇ sıɥʇ pɐǝɹ uɐɔ noʎ ɟI 

(使用http://www.fileformat.info/convert/text/upside-down.htm创建)

但请注意,有些字母只有非常粗略的倒置近似值, 比如

K --> ⋊ - RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT (U+22CA)

许多角色根本没有任何东西。所以这适合一些有趣的展示, 但不是生产应用程序。更好地翻转视图。

答案 1 :(得分:2)

如果你想绘制这样的字符串,子类NSLayoutManager并覆盖-drawGlyphsForGlyphRange:atPoint:,在发送CGAffineTransformMakeScale(-1, 1))之前用-showCGGlyphs:positions:count:font:matrix:attributes:inContext:设置当前上下文文本矩阵。 一个快速示例覆盖-drawGlyphsForGlyphRange:atPoint:以绘制文本“颠倒”,但不处理不同的属性,如下划线,strikethoughs ......

@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    // setup text objects
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:[@"Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." stringByReversingString]];

    MyLayoutManager *textLayout = [[MyLayoutManager alloc] init];

    [textStorage addLayoutManager:textLayout];

    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:self.view.bounds.size];

    [textLayout addTextContainer:textContainer];
    UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0,20,self.view.bounds.size.width,self.view.bounds.size.height-20)
                                               textContainer:textContainer];
    [self.view addSubview:textView];
}
@end

@implementation MyLayoutManager
- (void)drawGlyphsForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin
{
    NSUInteger i;
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    NSRange lineRange;

    for (i = glyphsToShow.location; i < NSMaxRange(glyphsToShow); i = NSMaxRange(lineRange))
    {
        CGRect lineRect = [self lineFragmentRectForGlyphAtIndex:i effectiveRange:&lineRange];

        NSRange characterRange = [self characterRangeForGlyphRange:lineRange actualGlyphRange:NULL];

        /* This sample don't take care of different font attributes (size, etc ..) for the each lines */
        UIFont *font = [[self.textStorage attributesAtIndex:characterRange.location effectiveRange:NULL] objectForKey:NSFontAttributeName];
        UIColor *color = [[self.textStorage attributesAtIndex:characterRange.location effectiveRange:NULL] objectForKey:NSForegroundColorAttributeName];

        CGGlyph *glyphs = malloc(sizeof(CGGlyph) * lineRange.length);
        CGSize *advances = malloc(sizeof(CGSize) * lineRange.length);

        [self getGlyphsInRange:lineRange glyphs:glyphs properties:NULL characterIndexes:NULL bidiLevels:NULL];

         CTFontGetAdvancesForGlyphs((CTFontRef)font, kCTFontHorizontalOrientation, glyphs, advances, lineRange.length);

        [color set];

        CGFontRef cgfont = CTFontCopyGraphicsFont((CTFontRef)font, NULL);

        // setup CGContextRef to draw text "upside-down"
        CGAffineTransform textMatrix = CGAffineTransformMakeScale(-1, 1);
        CGContextSetFont(ctx, cgfont);
        CGContextSetFontSize(ctx, [font pointSize]);
        CGContextSetTextMatrix(ctx, textMatrix);

        CGPoint position = lineRect.origin;
        position.x += origin.x;
        position.y += origin.y;

        int j;

        /* if you want the text to be right align, like the 'Lorem ipsum dolor' screenshot */
#if 1
        position.x += lineRect.size.width;
#else
        /* if you want the text to be left align */
        for (j = 0; j < characterRange.length; j++)
        {
            position.x += advances[j].width;
        }
#endif

        for (j = characterRange.length - 1; j >= 0; j--)
        {
            [self showCGGlyphs:&glyphs[j] positions:&position count:1 font:font matrix:textMatrix attributes:nil inContext:ctx];
            position.x -= advances[j].width;
        }

        CGFontRelease(cgfont);

        free(glyphs);
        free(advances);
    }
}
@end

text "upside-down" left aligned text "upside-down" right aligned