2014-03-02 39 views
1

如何反轉iOS7中NSString變量的文本? (我想顯示文字顛倒)。 注意:有很多解決方案將UILabel或UITextView顛倒過來,但這不是我想要的。如何在NSString中反轉(顛倒)文本

目前我能做到其中反轉串類別如下:

+ (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; 
} 

但我怎麼會變成文字顛倒嗎?

+1

˙uʍop-ǝpısdn對ɹoʇıuoɯɹnoʎ ǝɥʇǝɥʇǝɥʇɥʇɥʇɐǝɹɐɐʎɟI –

+0

@MartinR就是這樣。但是,如何以編程方式做到這一點? :D – motionpotion

回答

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) 

和許多字符什麼也沒有。所以這適合一些有趣的顯示, 但不適用於生產應用程序。更好地翻轉視圖。

+0

好的。如果我去翻轉uitextview,然後文本被複制到剪貼板,它被複製爲反轉或複製爲正常的方式了嗎? – motionpotion

+0

@motionpotion:正常的方式。我沒有辦法(我知道)將一個字符串標記爲「顛倒」。 –

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

+0

嗨,這是CoreText和TextKit的混合?這些字母是顛倒的(我問,因爲看起來我們只是通過向方法發送翻轉的上下文來做這件事)?謝謝。 – Unheilig

+0

@Unheilig是的,它既使用CoreText也使用TextKit,並且yes字母是真正顛倒的,這隻需將Font和TextMatrix設置爲當前的'CGContextRef'。但這僅僅是一個快速示例,展示了我們如何做這類事情,它並沒有做所有'-drawGlyphsForGlyphRange:atPoint:'應該做的並且可能被優化的東西。 – Emmanuel

+0

可能會進行優化,這意味着這裏存在一些性能問題?您介意引用可能需要優化的內容嗎?如果沒有太多要求,可以使用稍微更「完整」的版本進行更新嗎?謝謝。 – Unheilig