テキストを装飾する／NSAttributedStringの属性一覧

iOS 6 から、UILabel, UITextView, UITextFieldに、`attributedText` というNSAttributedString型のプロパティが追加されました。NSAttributedStringは文字列の属性を管理するクラスで、これを使用するとフォントや文字色、背景色、カーニング等の**属性をテキスト内の指定範囲に対して適用**することができるようになります。

![サンプル](http://f.cl.ly/items/2p3h0r391v3C2I1q2e0b/sample1.png)

##基本的な実装手順

基本的な手順は次の通りです。

###1. NSMutableAttributedStringオブジェクトを生成

`initWithString:`メソッドでオブジェクトを生成します。

````
NSString *str = @"NSAttributedString Sample";
NSMutableAttributedString *attrStr;
attrStr = [[NSMutableAttributedString alloc] initWithString:str];
````

引数には対象となる文字列を渡します。

###2. 属性をセット

`addAttribute:value:range:`メソッドを用いて属性、値、適用範囲をセットします。

````
// フォント
[attrStr addAttribute:NSFontAttributeName
                value:[UIFont fontWithName:@"Futura-CondensedMedium" size:17.]
                range:NSMakeRange(0, [attrStr length])];

// 背景色
[attrStr addAttribute:NSBackgroundColorAttributeName
                value:[UIColor colorWithRed:1. green:1. blue:.0 alpha:1.]
                range:NSMakeRange(0, [attrStr length])];

// 打ち消し線
[attrStr addAttribute:NSStrikethroughStyleAttributeName
                value:[NSNumber numberWithInt:3]
                range:[str rangeOfString:@"Sample"]];
````



###3. UILabelにセット

UILabelの`attributedText`プロパティに、作成したNSMutableAttributedStringオブジェクトをセットします。

````
[self.label setAttributedText:attrStr];
````

なお、サンプルではUILabelを用いていますが、UITextViewもUITextFieldもiOS6以上では同様の方法（attributedTextプロパティを使う）でテキストに装飾することができます。


![サンプル](http://f.cl.ly/items/0L211E1h0L0l1u3L2N43/sample2.png)

##属性と値について

上で載せたサンプルで`addAttribute:value:range:`メソッドに渡している属性は、それぞれ次のような効果があります。

- `NSFontAttributeName`：フォントを指定する
- `NSBackgroundColorAttributeName`：背景色を指定する
- `NSStrikethroughStyleAttributeName`：打ち消し線を指定する

そして、**属性毎に引数valueに指定できる値の型は違ってきます。**たとえば、属性`NSFontAttributeName`に対して値はUIFontオブジェクトを渡しますが、属性`NSBackgroundColorAttributeName`に対しては値としてUIColorオブジェクトを渡します。

属性毎に指定できる値の詳細は、

[NSAttributedString UIKit Additions Reference](http://developer.apple.com/library/ios/#documentation/uikit/reference/NSAttributedString_UIKit_Additions/Reference/Reference.html)

で確認することができます。


##影と文字色

文字色を指定する場合は`NSForegroundColorAttributeName`を使用します。値は`NSBackgroundColorAttributeName`と同様にUIColorオブジェクトを渡します。

また影をつける場合は`NSShadowAttributeName`を使用します。値にはNSShadowオブジェクトを渡します。

````
// NSShadowオブジェクト
NSShadow *shadow = [[NSShadow alloc] init];
[shadow setShadowColor:[UIColor colorWithRed:0. green:0. blue:0. alpha:1.]];
[shadow setShadowBlurRadius:4.0];
[shadow setShadowOffset:CGSizeMake(2, 2)];

// 影
[attrStr addAttribute:NSShadowAttributeName
                value:shadow
                range:NSMakeRange(0, [attrStr length])];

// 文字色
[attrStr addAttribute:NSForegroundColorAttributeName
                value:[UIColor colorWithRed:1. green:1. blue:0. alpha:1.]
                range:NSMakeRange(0, [attrStr length])];
````

![サンプル](http://f.cl.ly/items/3Q050r2x0h232B3W1C25/sample3.png)

##中抜き文字、下線、カーニング

`NSStrokeWidthAttributeName`を使用すると、中抜き文字にすることができます。値には線幅を指定します。中抜き文字の枠線の色を指定する場合は、`NSStrokeColorAttributeName`を使用します。

下線を引く場合は、`NSUnderlineStyleAttributeName`を使用します。値には整数のNSNumberオブジェクトを指定します。（ここでは定数`NSUnderlineStyleSingle`を使用しています。）

カーニングは`NSKernAttributeName`を使用します。値には浮動小数点数のNSNumberオブジェクトを指定します。

````
// 中抜き文字の線幅
[attrStr addAttribute:NSStrokeWidthAttributeName
                value:@5
                range:NSMakeRange(0, [attrStr length])];

// 中抜き文字の枠線の色、下線、カーニングを一度に指定
NSDictionary *attributes = @{NSStrokeColorAttributeName: [UIColor magentaColor],
                             NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle),
                             NSKernAttributeName: @1.5};

[attrStr addAttributes:attributes
                 range:[str rangeOfString:@"Sample"]];
````

また上記では`addAttributes:range:`メソッドを使用して**複数の属性と値を一度に指定**しています。同じ範囲に対して適用する場合等に便利です。

![サンプル](http://f.cl.ly/items/1S3y0o2u2B3A2s040m3Y/sample4.png)

##パラグラフスタイル

`NSParagraphStyleAttributeName`を使用すると、パラグラフスタイル（NSParagraphStyleオブジェクト）を指定することができます。NSParagraphStyleはアライメントやハイフネーションを指定するためのプロパティを持っています。

````
// NSMutableParagraphStyleオブジェクト
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];

// アラインメント
paragraph.alignment = NSTextAlignmentRight;

// ハイフネーション
paragraph.hyphenationFactor = 0.9;

// パラグラフスタイル
[attrStr addAttribute:NSParagraphStyleAttributeName
                value:paragraph
                range:NSMakeRange(0, [attrStr length])];
````

`hyphenationFactor`には0.0〜1.0の値を指定することができ、0.0でハイフネーション（行末で切れる単語をハイフンで繋ぐ）なし、1.0で常にハイフネーションを試みる設定となります。

![サンプル](http://f.cl.ly/items/2h0M3r162M0r0b3p2N1j/sample5.png)


##テキストエフェクト（iOS 7 or later）

`NSTextEffectAttributeName` でテキストエフェクトを指定することができます。指定できる値としては今のところ `NSTextEffectLetterpressStyle` （実体は文字列）しかありません。

```swift:swift
let attributedStr = NSMutableAttributedString(
    string: string,
    attributes: [NSTextEffectAttributeName: NSTextEffectLetterpressStyle])
```

こんな感じの効果が得られます。

![](https://qiita-image-store.s3.amazonaws.com/0/3180/a2d22c8b-e22c-ea7c-07f9-8243e5028a79.png)

> A graphical text effect giving glyphs the appearance of letterpress printing, in which type is pressed into the paper.


##リンク（iOS 7 or later）

`NSLinkAttributeName` で文字列にリンクを貼れます。値は NSURL 型を推奨、NSString でもOK。

```swift:swift
let attributedStr = NSMutableAttributedString(
    string: string,
    attributes: [NSLinkAttributeName: NSURL(string: "https://github.com/shu223")!])
```

![](https://qiita-image-store.s3.amazonaws.com/0/3180/582f93b3-a473-07b3-7786-b28c2c342aad.png)


##カスタム絵文字（iOS 7 or later）

`NSAttachmentAttributeName` を使用すると、文中に画像を挿入できます。つまり、**カスタム絵文字**的な使い方ができます。（Attachmentという名前なので、本当はもっと広い意味での用途を想定した機能だと思います）

```swift:swift
let attachment = NSTextAttachment()
attachment.image = UIImage(named: filename)!
attachment.bounds = CGRectMake(2, 0, 16, 21)

let attrStr = NSAttributedString(attachment: attachment)
attributedStr.insertAttributedString(attrStr, atIndex: attributedStr.length)
```

![](https://qiita-image-store.s3.amazonaws.com/0/3180/e99fd6d6-7233-5dff-6d77-375bebe295d4.png)

実装方法は下記記事を参考にさせていただきました。

- [UILabelに画像を表示する](http://qiita.com/nagisawks/items/ff8232e92a2e9525ab0b)


##NSAttributedStringを使用可能なUIKitのクラス

UILabel, UITextView, UITextFieldの、`attributedText` プロパティ以外にも、NSAttributedStringをセットできるプロパティ／メソッドがいくつかのUIKitのクラスに追加されています。

※いずれも要iOS6以上

**UIButton**

````
- (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state
````

**UIPickerView**

````
- (NSAttributedString *)pickerView:(UIPickerView *)pickerView
             attributedTitleForRow:(NSInteger)row
                      forComponent:(NSInteger)component
````

**UIRefreshControl**

````
@property (nonatomic, retain) NSAttributedString *attributedTitle
````

**UITextField**

````
@property(nonatomic,copy) NSAttributedString *attributedPlaceholder
```` 


##（2015.12.22追記）属性一覧

現行バージョン（iOS 9.2）で利用可能な属性を NSAttributedString.h から抜き出して、iOSバージョンごとに分類しました。

また、**本記事で解説したものを太字に**しています。

###iOS 6 以上で利用可能

- **NSFontAttributeName**
  - UIFont, default Helvetica(Neue) 12
- **NSParagraphStyleAttributeName**
  - NSParagraphStyle, default defaultParagraphStyle
- **NSForegroundColorAttributeName**
  - UIColor, default blackColor
- **NSBackgroundColorAttributeName**
  - UIColor, default nil: no background
- NSLigatureAttributeName
  - NSNumber containing integer, default 1: default ligatures, 0: no ligatures
- **NSKernAttributeName**
  - NSNumber containing floating point value, in points; amount to modify default kerning. 0 means kerning is disabled.
- **NSStrikethroughStyleAttributeName**
  - NSNumber containing integer, default 0: no strikethrough
- **NSUnderlineStyleAttributeName**
 - NSNumber containing integer, default 0: no underline
- **NSStrokeColorAttributeName**
  - UIColor, default nil: same as foreground color
- **NSStrokeWidthAttributeName**
  - NSNumber containing floating point value, in percent of font point size, default 0: no stroke; positive for stroke alone, negative for stroke and fill (a typical value for outlined text would be 3.0)
- **NSShadowAttributeName**
  - NSShadow, default nil: no shadow
- NSVerticalGlyphFormAttributeName
  - An NSNumber containing an integer value.  0 means horizontal text.  1 indicates vertical text.  If not specified, it could follow higher-level vertical orientation settings.  Currently on iOS, it's always horizontal.  The behavior for any other value is undefined.

###iOS 7 以上で利用可能

- **NSTextEffectAttributeName**
  - NSString, default nil: no text effect
- **NSAttachmentAttributeName**
  - NSTextAttachment, default nil
- **NSLinkAttributeName**
  - NSURL (preferred) or NSString
- NSBaselineOffsetAttributeName
  - NSNumber containing floating point value, in points; offset from baseline, default 0
- NSUnderlineColorAttributeName
  - UIColor, default nil: same as foreground color
- NSStrikethroughColorAttributeName
  - UIColor, default nil: same as foreground color
- NSObliquenessAttributeName
  - NSNumber containing floating point value; skew to be applied to glyphs, default 0: no skew
- NSExpansionAttributeName
  - NSNumber containing floating point value; log of expansion factor to be applied to glyphs, default 0: no expansion
- NSWritingDirectionAttributeName
  -  NSArray of NSNumbers representing the nested levels of writing direction overrides as defined by Unicode LRE, RLE, LRO, and RLO characters.  The control characters can be obtained by masking NSWritingDirection and NSTextWritingDirection values.  LRE: NSWritingDirectionLeftToRight|NSWritingDirectionEmbedding, RLE: NSWritingDirectionRightToLeft|NSWritingDirectionEmbedding, LRO: NSWritingDirectionLeftToRight|NSWritingDirectionOverride, RLO: NSWritingDirectionRightToLeft|NSWritingDirectionOverride,

iOS 8、9 では新規追加されなかったようです。