11

重複の可能性:
UITextView : ラップ情報でテキストを取得

私は NSString ライブラリと、次のような長い文字列を取ることができる関数の多数のライブラリを探しています:

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui.

幅を示す CGSize または浮動小数点数、および使用されているフォントと共に、\n 区切りと単語が折り返された文字列を返します。

結果(おおよそ):

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac\n
egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet.\n
 Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. \n
placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra.\n
 Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi.\n
 Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci,\n
 sagittis tempus lacus enim ac dui. 

UITextViews などがこれを行うことは既に知っていますが、生の OpenGL ランドスケープでテキストをレンダリングする必要があるため、これは役に立ちません。そのため、通常の UI 要素は使用していません。

これは、フレームワークとして存在するか、どこかにパブリック クラスとして存在することを知っています。これを処理する統一された方法が見つかりません。

[NSString sizeWithFont:forWidth:lineBreakMode:] に近いと思いますが、サイズは必要ありません。文字列自体が必要です。

4

2 に答える 2

9

テキストをラップするたびに、テキスト エンジンがまさにそれを行うため、この車輪を再発明する必要はまったくありません。テキストエンジンとは?コアテキストです。Core Text のレベルまでドロップダウンし、CTFramesetter にテキストをレイアウトしてもらうと、結果の CTLines を要求することで、改行が配置されている場所を知ることができます。

ドキュメントはあなたを始めるのに役立ちます:

http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/CoreText_Programming/Operations/Operations.html

また、Web 上には優れたチュートリアルがたくさんあります。

簡単な例:

NSString* s = @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
@"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
@"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
@"nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor "
@"in reprehenderit in voluptate velit esse cillum dolore eu fugiat "
@"nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
@"sunt in culpa qui officia deserunt mollit.";
NSAttributedString* text = [[NSAttributedString alloc] initWithString:s];

CTFramesetterRef fs =
CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)text);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0,0,200,100000));
CTFrameRef f = CTFramesetterCreateFrame(fs, CFRangeMake(0, 0), path, NULL);
CTFrameDraw(f, NULL);

NSArray* lines = (__bridge NSArray*)CTFrameGetLines(f);
for (id aLine in lines) {
    CTLineRef theLine = (__bridge CTLineRef)aLine;
    CFRange range = CTLineGetStringRange(theLine);
    NSLog(@"%ld %ld", range.location, range.length);
}
CGPathRelease(path);
CFRelease(f);
CFRelease(fs);

ご覧のとおり、出力にはラップされたテキストの各行の範囲が表示されます。これはあなたが求めているものではありませんか?

于 2012-11-27T16:10:40.570 に答える
1

これを行う工場出荷時の方法がないように思われるため、この密接に関連するスタックで導入されたソリューションに基づいて、これを処理するクラス関数の構築を開始しました。

+ (NSString*)wrappedString:(NSString*)string withFont:(UIFont*)font andWidth:(float)width {
    NSMutableString *resultString = [[NSMutableString alloc] initWithString:@""];

    CGSize textSize = [string sizeWithFont:font];
    float textWidth = textSize.width;
    if (textWidth < width) {
        return string;
    }
    float wordLength;
    float lineLength;
    NSUInteger length = [string length];
    unichar buffer[length];
    [string getCharacters:buffer range:NSMakeRange(0, length)];

    NSString *singleLine = @"";
    NSString *word = @"";
    NSString *longWord = @"";

    for (NSUInteger i = 0; i < length; i++) {

        unichar character = buffer[i];
        if (character != '\n') {
            word = [NSString stringWithFormat:@"%@%c", word, character];
        }

        if (character == '\n') {
            float wordLength = [word sizeWithFont:font].width;
            float lineLength = [singleLine sizeWithFont:font].width;
            if ((lineLength + wordLength) > width) {
                [resultString appendString:singleLine];
                [resultString appendString:@"\n"];
                singleLine = @"";
                singleLine = [singleLine stringByAppendingFormat:@"%@\n",word];
                word = @"";
            } else {
                singleLine = [singleLine stringByAppendingString: word];
                word = @"";
                [resultString appendString:singleLine];
                [resultString appendString:@"\n"];
                singleLine = @"";
            }
        }

        else if (character == ' ') {
            float wordLength = [word sizeWithFont:font].width;
            float lineLength = [singleLine sizeWithFont:font].width;

            if ((lineLength + wordLength) > width) {
                if (wordLength > textWidth) {
                    [resultString appendString:singleLine];
                    [resultString appendString:@"\n"];
                    singleLine = @"";
                    int j = 0;
                    for (; j < [word length]; j++) {
                        unichar longChar = [word characterAtIndex:j];
                        longWord = [NSString stringWithFormat:@"%@%c", longWord, longChar];
                        float longwordLength = [longWord sizeWithFont:font].width;
                        float longlineLength = [singleLine sizeWithFont:font].width;
                        if ((longlineLength + longwordLength) >= width) {
                            singleLine = [singleLine stringByAppendingString:longWord];
                            word = @"";
                            longWord = @"";
                            break;
                        }
                    }

                }
                [resultString appendString:singleLine];
                [resultString appendString:@"\n"];
                singleLine = @"";
            }
            singleLine = [singleLine stringByAppendingString: word];
            word = @"";
        }
    }

    wordLength = [word sizeWithFont:font].width;
    lineLength = [singleLine sizeWithFont:font].width;

    if (wordLength > 0) {
        if ((lineLength + wordLength) > width) {
            [resultString appendString:singleLine];
            [resultString appendString:@"\n"];
            singleLine = @"";
        }
        singleLine = [singleLine stringByAppendingString:word];
    }


    if (lineLength > 0) {
        [resultString appendString:singleLine];
        [resultString appendString:@"\n"];
    }
    return resultString;
}
于 2012-11-27T14:12:33.683 に答える