iOSアプリでicon fontを使用してアイコンを表示する

# はじめに
icon fontを使用して、アイコンを表示してみます。

今回は、[Icon Font & SVG Icon Sets ❍ IcoMoon](https://icomoon.io/app/#/select)で生成したttfファイルのフォントを使用します。

<img width="893" alt="スクリーンショット 2017-08-09 13.15.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/103695/9e0885c4-672a-08bf-8bff-8b47260340f2.png">


# 開発環境
|category | Version| 
|---|---|
| Swift | 3.1 |
| XCode | 8.3.3 |

# 導入手順1. Xcodeにttfファイルを追加する

ドラッグ＆ドロップで追加します。（targetのチェックを忘れずに。）

![スクリーンショット 2017-08-09 8.34.46.png](https://qiita-image-store.s3.amazonaws.com/0/103695/640c33e6-230c-f5b1-d619-4b0455a3659f.png)

![スクリーンショット 2017-08-09 8.38.33.png](https://qiita-image-store.s3.amazonaws.com/0/103695/815d9e3a-d4dd-e2c7-8666-f984edb2bf69.png)

# 導入手順2. info.plistのFonts provided by applicationを設定する

info.plistの「Fonts provided by application」に先ほど追加したttfファイルのファイル名を記載します。
複数のcustom fontを使用する場合は、Arrayのitemを追加してファイル名を記載します。

![スクリーンショット 2017-08-09 8.55.49.png](https://qiita-image-store.s3.amazonaws.com/0/103695/0067c9cf-174a-b49f-e4b1-d6bd2ba22717.png)

![スクリーンショット 2017-08-09 9.00.04.png](https://qiita-image-store.s3.amazonaws.com/0/103695/9364e3e0-96b9-4ca4-fb3d-e2d75f227147.png)

以上で導入は完了です。

# ttfファイルのPostScript名を確認する

terminalで以下を実行することで確認できます。
`$ mdls <ttfファイルのPATH>`
例：
`$ mdls /Users/yuki/Desktop/icomoon/fonts/icomoon.ttf`

<img width="500" alt="スクリーンショット 2017-08-09 8.46.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/103695/7b1939af-87b3-e9c8-f225-a66411c3117f.png">

**PostScript名は、ソースコードでUIFontのインスタンスを生成する際に使用します。**
`let font = UIFont(name: <PostScript名>, size: 20.0)`
上記の例の場合：
`let font = UIFont(name: "icomoon", size: 20.0)`


# UILabelに表示してみる

使用するiconのicon名をenumで定義しておきます。

```swift
/// IconFont名
enum IconFont: String {
    
    /// tongue
    case tongue = "\u{e9e3}"
    
    /// tongue2
    case highlightedTongue = "\u{e9e4}"
    
    /// cool
    case cool = "\u{e9eb}"
    
    /// cool2
    case highlightedCool = "\u{e9ec}"
    
    /// confused
    case confused = "\u{e9f5}"
    
    /// confused2
    case highlightedConfused = "\u{e9f6}"
    
    /// hipster
    case hipster = "\u{e9f9}"
    
    /// hipster2
    case highlightedHipster = "\u{e9fa}"
}
```

上記enumでicon名を指定して、UILabelに表示してみます。

```swift
// nameには、PostScript名をセット
guard let font = UIFont(name: "icomoon", size: 20) else { return }
let attributedString = NSAttributedString(string: "custom icon font: " + IconFont.tongue.rawValue,
                                          attributes: [NSFontAttributeName: font])
label.attributedText = attributedString
```

![2017-08-09 13.34.57.png](https://qiita-image-store.s3.amazonaws.com/0/103695/0a71db59-8f46-d9f6-2b90-5a16b63018c9.png)

UILabelにアイコンを表示することができました！！

# UIImageに変換する

TabBarのアイコンに使用したい場合等テキストだと都合の悪い場合もあるので、
UIImageに変換するextensionも用意します。

```swift
extension UIImage {
    
    /// IconFontからUIImageを生成する
    ///
    /// - Parameters:
    ///   - icon: IconFont名
    ///   - fontSize: 基のフォントサイズ (default: 20.0)
    ///   - rect: 生成する画像のサイズ (default: CGSize(width: 20.0, height: 20.0))
    ///   - color: 生成する画像の色 (default: .blue)
    /// - Returns: 画像
    class func iconFont(icon: IconFont,
                        fontSize: CGFloat = 20.0,
                        rect: CGSize = CGSize(width: 20.0, height: 20.0),
                        color: UIColor = .blue) -> UIImage? {
        
        guard let font = UIFont(name: "icomoon", size: fontSize) else { return nil }
        UIGraphicsBeginImageContextWithOptions(rect, false, 0.0)
        let attributes = [NSForegroundColorAttributeName: color,
                          NSFontAttributeName: font]
        let attributedString = NSAttributedString(string: icon.rawValue,
                                                  attributes: attributes)
        
        let context = NSStringDrawingContext()
        let boundingRect = attributedString.boundingRect(with: CGSize(width: fontSize, height: fontSize),
                                                         options: .usesLineFragmentOrigin,
                                                         context: context)
        
        let imageRect = CGRect(x: (rect.width / 2.0) - (boundingRect.size.width / 2.0),
                               y: (rect.height / 2.0) - (boundingRect.size.height / 2.0),
                               width: rect.width,
                               height: rect.height)
        
        attributedString.draw(in: imageRect)
        let iconImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return iconImage
    }
}
```

先ほどはUILabelにアイコンを表示してみましたが、
今度は上記extensionでUIImageに変換してUIImageViewに表示してみます。

```
// UIImageViewに画像をセット
imageView1.image = UIImage.iconFont(icon: .tongue, color: .orange)
imageView2.image = UIImage.iconFont(icon: .cool, color: .green)
imageView3.image = UIImage.iconFont(icon: .confused, color: .red)
imageView4.image = UIImage.iconFont(icon: .hipster, color: .blue)
```

![2017-08-09 13.35.55.png](https://qiita-image-store.s3.amazonaws.com/0/103695/ae2d87c1-9e23-7d2a-b071-da0b6b9e612d.png)

UIImageViewでもアイコンを表示することができました！！

# さいごに
Githubに作成したサンプルをあげました。
[サンプルコード](https://github.com/stv-yokudera/ios-custom-font-demo/tree/develop)