[iOS][Swift3.0] NSAttributedStringが直感的に書けるようになるSwiftyAttributes

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

テキストを装飾するNSAttributedStringは文字の表現が豊かになり便利な反面、(個人の主観ですが) 記法がすこし面倒です。
今回はそんなNSAttributedStringが書きやすくなるSwiftyAttributesといういライブラリを試してみました。ライセンスはMITです。

https://github.com/eddiekaiger/SwiftyAttributes

検証環境

今回は下記環境で試しています。

Xcode 8.2
Swift 3.0.2
CocoaPods 1.0.0

準備

CocoaPodsで追加します。

use_frameworks!
target "ターゲット名"
pod 'SwiftyAttributes'

post_install do |installer|
    installer.pods_project.targets.each do |target|
target.build_configurations.each do |configuration|
    configuration.build_settings['SWIFT_VERSION'] = "3.0"
end
    end
end

文字を装飾する

簡単な使い方

SwiftyAttributesではStringの拡張として各種装飾のプロパティが用意されています。
下記は文字の色を赤にする例です。(各種装飾はwith○○形式で定義されています)

"対象となる文字列".withTextColor(.red)

sample

複数

複数のAttributeを適用したい場合はつなげて記述します。
例として、下記は文字を赤くして斜めにして青い下線を引いています。

"対象となる文字列".withTextColor(.red).withObliqueness(0.8).withUnderlineStyle(.styleSingle).withUnderlineColor(.blue)

sample

サンプル

各種効果を適用させてみました。

let baseText = "吾輩は猫である"

// フォント .withFont(UIFont)
sample1Label.attributedText = baseText.withFont(UIFont.boldSystemFont(ofSize: 24.0))

// 文字色 .withTextColor(UIColor)
sample2Label.attributedText = baseText.withTextColor(.orange)

// 背景色 .withBackgroundColor(UIColor)
sample3Label.attributedText = baseText.withBackgroundColor(.cyan)

// カーニング .withKern(Double)
sample4Label.attributedText = baseText.withKern(8.0)

// 影 .withShadow(NSShadow)
let shadow = NSShadow.init()
shadow.shadowOffset = CGSize(width: 3, height: 3)
shadow.shadowColor = UIColor.orange // 影の色
shadow.shadowBlurRadius = 4.0       // ぼかしの半径
sample5Label.attributedText = baseText.withShadow(shadow)

// 横に拡大? .withExpansion(Double)
sample6Label.attributedText = baseText.withExpansion(0.8)

// ななめ化 .withObliqueness(Double)
sample7Label.attributedText = baseText.withObliqueness(0.8)

// 線 .withStrokeWidth(Double).withStrokeColor(UIColor)
sample8Label.attributedText = baseText.withStrokeWidth(1.0).withStrokeColor(.blue)

// 下線 .withUnderlineStyle(NSUnderlineStyle).withUnderlineColor(UIColor)
sample9Label.attributedText = baseText.withUnderlineStyle(.styleDouble).withUnderlineColor(.magenta)

// 取り消し線 .withStrikethroughStyle(NSUnderlineStyle).withStrikethroughColor(UIColor)
sample10Label.attributedText = baseText.withStrikethroughStyle(.styleSingle).withStrikethroughColor(.red)

// 段落スタイル .withParagraphStyle(NSMutableParagraphStyle)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
sample11Label.attributedText = baseText.withParagraphStyle(paragraphStyle)

// 文字の方向 .withWritingDirections([WritingDirection])
sample12Label.attributedText = baseText.withWritingDirections([.rightToLeftOverride])

// リンク .withLink(URL)
sample13TextView.attributedText = baseText.withLink(URL(string: "https://classmethod.jp/")!)

sample

まとめて適用するケース

装飾をまとめて適用する場合は.withAttributes([Attribute])形式で記載する方が便利かもしれません。 SwiftyAttributesではAttributeというenumが定義されており、そのリストを定義することが出来ます。

たとえば、

"対象となる文字列".withTextColor(.red).withObliqueness(0.8).withUnderlineStyle(.styleSingle).withUnderlineColor(.blue)

"対象となる文字列".withAttributes([.textColor(.red), .obliqueness(0.8), .underlineStyle(.styleSingle), .underlineColor(.blue)])

のように記述することが出来ます。

サンプル

複数の文字に同じ装飾を適用しています。

let attributes: [Attribute] = [.textColor(.white), .backgroundColor(.darkGray), .underlineStyle(.styleDouble), .underlineColor(.magenta)]
sample1Label.attributedText = "Hello World".withAttributes(attributes)
sample2Label.attributedText = "Bonjour le monde".withAttributes(attributes)
sample3Label.attributedText = "Ciao mondo".withAttributes(attributes)

sample

AttributedStringをつなげる

SwiftyAttributesではNSAttributedString + NSAttributedStringのオペレーターが定義されています。
そのため、 + で装飾文字列をつなげることができます。

サンプル

let attachment = NSTextAttachment()
attachment.image = UIImage(named: "cat")
attachment.bounds = CGRect(x: 0, y: -2, width: 16, height: 16)
sampleLabel.attributedText = "吾輩は".withTextColor(UIColor.brown) + NSAttributedString(attachment: attachment) + "である".withTextColor(UIColor.brown)

サンプル

さいごに

今回、検証してみてSwiftyAttributesを使ったwithLigaturesとwithAttachmentの適用が自分の環境では上手くいきませんでした。(ligaturesの方はフォントが合字に対応していなかったのかもしれません・・・)
attachmentの方は「AttributedStringをつなげる」のサンプルに記載したように+でつなげるのであれば問題ありませんでした。念のため、ご留意ください。