Cocoa API解説(macOS/iOS)

iOS , Mac アプリケーション開発のために使われる主要フレームワークの日本語情報です。

目次

NSAttributedStringクラス

INDEX>Foundation>NSAttributedString

変更不可な属性付き文字列クラス

編集時のバージョン OS X 10.8 iOS 6.1
apple(OS X)

apple(iOS)

解説

変更不可な属性付き文字クラス

継承 NSObject
準拠 NSCoding
NSCopying
NSMutableCopying
NSObject (NSObject)
フレームワーク /System/Library/Frameworks/Foundation.framework
使用可能 Mac OS X v10.0以降
iOS 3.2以降
定義 NSAttributedString.h

概要

変更不可な属性付き文字列のクラスです。作成・初期化した後、その内容を変更することはできません。変更可能な属性付き文字列はNSMutableAttributedStringクラスを使用します。
利用可能なiOSのバージョンが3.2以降となっているように、iPadの登場とともに使えるようになったクラスです。

文字の属性とはフォント、サイズ、色、太字などの文字スタイルに加え、段落スタイル、日本語での縦書き表示の際の文字の向きなどが含まれます。

iOS5.1ではUIKitには描画するAPIは無いので、iOSではCoreTextフレームワークとともにこのクラスを使用します。(iOS 6で描画する関数ができました。)

オブジェクトの作成

NSAttributedStringを作成する時には、allocで作成して文字列から初期化するメソッド(– initWithString)、他の属性付き文字列から初期化するメソッド(– initWithAttributedString)、文字列と属性の辞書から初期化するメソッド(– initWithString:attributes)があります。3番目の文字列と属性の辞書から作る方法だと柔軟に設定を変更することができます。辞書で設定できるキーの一覧はCTStringAttributes.hにあります。
一例を挙げると、文字色(kCTForegroundColorAttributeName)、下線の形状(kCTUnderlineStyleAttributeName)、リガチャを行うか(kCTLigatureAttributeName)などです。@"CTForegroundColor"や@"NSFont"などの文字列定数もキーとして使うことができます。

文字情報の取得

文字列を取得するには(– string)を使います。文字列の長さを取得するには(– length)を使います。

属性情報の取得

指定した位置の文字と同じ属性の範囲を調べるには(– attributesAtIndex:effectiveRange)メソッドを使います。attributesAtIndex:の引数に調べたい文字の番号(0からはじまる)を渡し、effectiveRange:の引数にはNSRangeのポインタを渡します。メソッドを呼び出すと属性の辞書が返され、NSRangeに同じ属性を持つ範囲が返されます。指定した範囲内で上記を調べるメソッド(– attributesAtIndex:longestEffectiveRange:inRange)もあります。

指定した位置の文字と指定した属性が同じ範囲を調べるには(– attribute:atIndex:effectiveRange)メソッドを使います。attribute:にkCTForegroundColorAttributeName、kCTUnderlineStyleAttributeNameなどの属性を渡してやります。こちらも同じく指定した範囲内で上記を調べるメソッド(– attribute:atIndex:longestEffectiveRange:inRange)があります。

比較

属性付き文字列同士が同じであるかを比較するには(– isEqualToAttributedString)メソッドを使います。

部分的な取り出し

属性付き文字列から範囲を指定して部分的に属性付き文字列として取り出すには(– attributedSubstringFromRange)を使います。

同じ属性の列挙

指定した範囲の同じ属性を持つ範囲を列挙するには(– enumerateAttributesInRange:options:usingBlock)メソッドを使います。指定した範囲の特定の属性を列挙するには(– enumerateAttribute:inRange:options:usingBlock)を使います。
この二つのメソッドは同じ属性の範囲を順番に返してくれますので、同じ属性の物に対して次々と処理を行う場合に便利です。


サンプルCoreTextを使って縦書き

//#import <CoreText/CoreText.h>が必要

- (void)drawRect:(CGRect)rect {

	CGContextRef context = UIGraphicsGetCurrentContext();
	
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect bounds = CGRectMake((CGFloat)rect.origin.x-0,
                               (CGFloat)rect.origin.y+400.0,
                               (CGFloat)rect.size.width-0,
                               (CGFloat)rect.size.height-500);
    CGPathAddRect(path, NULL, bounds);
    
    //フォント
    CTFontRef aFont1 = CTFontCreateWithName(CFSTR("HiraKakuProN-W6"), 20, NULL);
    CTFontRef aFont2 = CTFontCreateWithName(CFSTR("HiraMinProN-W6"), 18, NULL);
    //カラー
    CGColorRef darkGrayColor = [[UIColor darkGrayColor] CGColor];
    CGColorRef redColor = [[UIColor redColor] CGColor];
    
    //段落スタイル
    float_t lineHeight = 20.0;
    id paragraphStyleAttr = ((^ {
        
        CTParagraphStyleSetting paragraphStyles[] = (CTParagraphStyleSetting[]){
            (CTParagraphStyleSetting)
                { kCTParagraphStyleSpecifierLineHeightMultiple, sizeof(float_t), (float_t[]){ 0.01f } },
            (CTParagraphStyleSetting)
                { kCTParagraphStyleSpecifierMinimumLineHeight, sizeof(float_t), (float_t[]){lineHeight } },
            (CTParagraphStyleSetting)
                { kCTParagraphStyleSpecifierMaximumLineHeight, sizeof(float_t), (float_t[]){lineHeight } },
            (CTParagraphStyleSetting)
                { kCTParagraphStyleSpecifierLineSpacing, sizeof(float_t), (float_t[]){ 0.0f } },
            (CTParagraphStyleSetting)
                { kCTParagraphStyleSpecifierMinimumLineSpacing, sizeof(float_t), (float_t[]){ 0.0f } },
            (CTParagraphStyleSetting)
                { kCTParagraphStyleSpecifierMaximumLineSpacing, sizeof(float_t), (float_t[]){ 0.0f } }
            
        };
        
        CTParagraphStyleRef paragraphStyleRef = CTParagraphStyleCreate(paragraphStyles, sizeof(paragraphStyles) / sizeof(CTParagraphStyleSetting));
        return (__bridge_transfer id)paragraphStyleRef;
        
    })());

        //属性辞書
    NSDictionary *fontAttributes1 = [NSDictionary dictionaryWithObjectsAndKeys:
                                    (__bridge id)aFont1, @"NSFont",
                                    (__bridge id)darkGrayColor, @"CTForegroundColor",
                                     [NSNumber numberWithBool:YES], @"CTVerticalForms",
                                     [NSNumber numberWithBool:YES],kCTLigatureAttributeName,
                                     paragraphStyleAttr, kCTParagraphStyleAttributeName,
                                    nil];
    
    //属性辞書
    NSDictionary *fontAttributes2 = [NSDictionary dictionaryWithObjectsAndKeys:
                                    (__bridge id)aFont2, @"NSFont",
                                    (__bridge id)redColor, @"CTForegroundColor",
                                    [NSNumber numberWithBool:YES], @"CTVerticalForms",
                                     paragraphStyleAttr, kCTParagraphStyleAttributeName,
                                    nil];
    CFRelease(aFont1);
    CFRelease(aFont2);
    CFRelease(darkGrayColor);
    CFRelease(redColor);
    
    NSAttributedString *grayString = [[NSAttributedString alloc] initWithString:@"みなさん、こんにちは。\nこれはNSAttributedStringとCoreTextを使って、縦書き表示をするサンプルです。\n割と簡単に表示できるでしょ?\nいろいろ試してみてください。"  attributes:fontAttributes1];
    NSAttributedString *redString = [[NSAttributedString alloc] initWithString:@"ここから属性を変えて追加した赤い文字です。"  attributes:fontAttributes2];
    
    NSMutableAttributedString *amText = [[NSMutableAttributedString alloc] initWithAttributedString:grayString];
    [amText appendAttributedString:redString];
    
    CFMutableAttributedStringRef cfamText = (__bridge_retained CFMutableAttributedStringRef)amText;

    //属性付きテキストでフレームセッタを作成
    CTFramesetterRef framesetter =  CTFramesetterCreateWithAttributedString(cfamText);

    //属性付きテキストを解放
    CFRelease(cfamText);
    
    //フレーム作成
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, 
                                                (__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
                                                                  [NSNumber numberWithUnsignedInt:kCTFrameProgressionRightToLeft], @"CTFrameProgression", nil]);
    
    
    //フレーム描画
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
	CGContextScaleCTM(context, 1.0, -1.0);
    
	CGContextSaveGState(context);
	CTFrameDraw(frame, context);
	CGContextRestoreGState(context);
    
	CGContextSetTextMatrix(context, CGAffineTransformIdentity);
	CGContextSetTextPosition(context, 0, 0);
    
    CFRelease(frame); 
    CFRelease(framesetter);
 
    
}

適合するプロトコル

NSCoding
encodeWithCoder:
initWithCoder:
NSCopying
copyWithZone:
NSMutableCopying
mutableCopyWithZone:

メソッド

NSAttributedString オブジェクトの作成
– initWithString 10.0 3.2〜
– initWithAttributedString 10.0 3.2〜
– initWithString:attributes 10.0 3.2〜
文字情報を取得
– string 3.2〜
– length 10.0 3.2〜
属性情報を取得
– attributesAtIndex:effectiveRange 10.0 3.2〜
– attributesAtIndex:longestEffectiveRange:inRange 10.0 3.2〜
– attribute:atIndex:effectiveRange 3.2〜
– attribute:atIndex:longestEffectiveRange:inRange 3.2〜
属性文字列の比較
– isEqualToAttributedString 3.2〜
部分的に取り出す
– attributedSubstringFromRange 3.2〜
属性を列挙
– enumerateAttribute:inRange:options:usingBlock 10.6〜 4.0〜
– enumerateAttributesInRange:options:usingBlock 10.6〜 4.0〜

定数

NSAttributedStringEnumerationOptions iOS4.0


サブクラス化の注意