はじめに
iOSアプリ開発では、複数行に渡る文章の行間( lineSpacing
)など、文字列に複雑な装飾を施す場合、 NSAttributedString
を生成する必要があります。
生成方法が複雑なので、引数を渡してかんたんに生成する拡張関数を実装しました。
環境
- OS:macOS Mojave 10.14.6
- Xcode:11.3.1 (11C504)
- Swift:5.1.3
実装
イニシャライザを拡張関数として定義します。
import UIKit
extension NSAttributedString {
convenience init(font: UIFont, color: UIColor, lineSpacing: CGFloat, alignment: NSTextAlignment, string: String) {
var attributes: [NSAttributedString.Key: Any] = [
.font: font,
.foregroundColor: color
]
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = lineSpacing
paragraphStyle.alignment = alignment
attributes.updateValue(paragraphStyle, forKey: .paragraphStyle)
self.init(string: string, attributes: attributes)
}
}
使い方
拡張関数として定義したイニシャライザを呼び出すのみです。
@IBOutlet private weak var descriptionLabel: UILabel! {
willSet {
newValue.attributedText = NSAttributedString(
font: .systemFont(ofSize: 16.0),
color: .blue,
lineSpacing: 6.0,
alignment: .left,
string: "description"
)
}
}
拡張関数の定義前と比べると、スッキリ書けることがわかります。
@IBOutlet private weak var descriptionLabel: UILabel! {
willSet {
var attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 16.0),
.foregroundColor: UIColor.blue
]
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 6.0
paragraphStyle.alignment = .left
attributes.updateValue(paragraphStyle, forKey: .paragraphStyle)
newValue.attributedText = NSAttributedString(string: "description", attributes: attributes)
}
}
おわりに
今回紹介した拡張関数は、私が必要としている最低限の引数のみ追加しているので、必要に応じてカスタマイズしてください。
NSMutableAttributedString
として可変に扱う場合にもカスタマイズが必要です。
おまけ:他の方法
Twitterで他の人がどう NSAttributedString
を生成しているか伺ったので、紹介します。
NSAttributedString
を定数化する
よくアプリ内で使うAttributeを定数化ですね...
— 大渕雄生@未踏2020! (@obuchi_yuki) June 25, 2020
enum Attributeという名前空間作ってその中に static で書いていっちゃう感じです。
行間の大きさが画面間で変わることも少ないので、 NSAttributedString
ごと定数化するのはありだと思いました。
定数化の実装時に私が紹介した拡張関数を使うと、よりスッキリ書けると思います。
String
から生成できるようにする
自分は極力楽したくて
— もちゅる|【転職活動中】フルリモートパパエンジニア (@mothule) June 25, 2020
"文字列".decode([DecoratableType])
で書けるlibを書いた https://t.co/z3gngLRzcJ
String
に NSAttributedString
を返す拡張関数を追加する方法です。
こちらもわかりやすくていいと思いました。
ただ文字列をローカライズしている場合、若干読みづらくなるかもしれません。