Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Handling rich text in Swift
Search
Kishikawa Katsumi
August 20, 2016
Programming
17
6.7k
Handling rich text in Swift
Handling rich text
in Swift
iOSDC Japan 2016
Kishikawa Katsumi
August 20, 2016
Tweet
Share
More Decks by Kishikawa Katsumi
See All by Kishikawa Katsumi
iOSDC 2024 SMBファイル共有をSwiftで実装する
kishikawakatsumi
1
220
Enhancing Applications with Accessibility API
kishikawakatsumi
3
4k
Mastering SwiftSyntax
kishikawakatsumi
4
6.1k
My SwiftData Review
kishikawakatsumi
7
1.4k
Swift Expression Macros: a practical introduction
kishikawakatsumi
3
1.9k
Xcode Cloudの評価
kishikawakatsumi
2
1.3k
Regular expressions basics/正規表現の基本
kishikawakatsumi
7
760
家のいろいろな数値を計測する
kishikawakatsumi
4
2.3k
GitHub Actionsでテストの結果をわかりやすく表示する
kishikawakatsumi
1
1.2k
Other Decks in Programming
See All in Programming
Building a macOS screen saver with Kotlin (Android Makers 2025)
zsmb
1
130
自分のために作ったアプリが、グローバルに使われるまで / Indie App Development Lunch LT
pixyzehn
1
150
gen_statem - OTP's Unsung Hero
whatyouhide
1
190
Going Structural with Named Tuples
bishabosha
0
200
Agentic Applications with Symfony
el_stoffel
2
250
SQL Server ベクトル検索
odashinsuke
0
160
Devinのメモリ活用の学びを自社サービスにどう組み込むか?
itarutomy
0
2k
ミリしらMCP勉強会
watany
4
720
Youtube Lofier - Chrome拡張開発
ninikoko
0
2.4k
小さく段階的リリースすることで深夜メンテを回避する
mkmk884
2
160
Deoptimization: How YJIT Speeds Up Ruby by Slowing Down / RubyKaigi 2025
k0kubun
0
150
新しいPHP拡張モジュールインストール方法「PHP Installer for Extensions (PIE)」を使ってみよう!
cocoeyes02
0
230
Featured
See All Featured
Writing Fast Ruby
sferik
628
61k
Build The Right Thing And Hit Your Dates
maggiecrowley
35
2.6k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
32
2.2k
The Language of Interfaces
destraynor
157
24k
A Modern Web Designer's Workflow
chriscoyier
693
190k
The Cost Of JavaScript in 2023
addyosmani
48
7.7k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2.2k
Measuring & Analyzing Core Web Vitals
bluesmoon
6
380
Building a Scalable Design System with Sketch
lauravandoore
462
33k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
7
640
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.5k
Into the Great Unknown - MozCon
thekraken
36
1.7k
Transcript
Handling rich text in Swift iOSDC Japan 2016 Katsumi Kishikawa
kk@realm.io
Katsumi Kishikawa Realm Inc. kk@realm.io
kk@realm.io
kk@realm.io
kk@realm.io
kk@realm.io
Agenda ˖ J04ךذؗأزٖ؎،ؐزחאְג ˖ ة؎هؚٓؿ؍ך㛇燉 ˖ 5FYU,JUך㛇燉ה䘔欽 kk@realm.io
iOS 7Ҏ߱ͷςΩετϨΠΞτ kk@realm.io
TextKit kk@realm.io
TextKitͱ ˖ 넝鸞זٌتٝذؗأزٖ؎،ؐز٥ٖٝت ؚٔٝؒٝآٝ ˖ $PSF5FYUד⡲גְ ˖ 6*,JUהך窟さ kk@realm.io https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/CustomTextProcessing/CustomTextProcessing.html
UILabel kk@realm.io
kk@realm.io UILabelΛී௨ʹ͏
kk@realm.io ώϥΪϊͱγεςϜϑΥϯτ UIFont(name: "HiraginoSans-W3", size: 32) UIFont.systemFontOfSize(32)
kk@realm.io ώϥΪϊͱγεςϜϑΥϯτ
kk@realm.io ώϥΪϊͱγεςϜϑΥϯτ
kk@realm.io General Header
kk@realm.io ΞϧϑΝϕοτΛؚ·ͳ͍߹
ߦͷߴ͞ԿͰܾ·Δ͔ kk@realm.io
kk@realm.io Font metrics https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html
kk@realm.io Font metrics https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html
kk@realm.io Font metrics
kk@realm.io Font metrics Baseline X-Height Cap height Ascent Descent
kk@realm.io ώϥΪϊಛघͳϝτϦΫεΛ࣋ͭ
kk@realm.io ʢࢀߟʣNoto Sans CJK JP
let label = UILabel(frame: view.bounds) label.backgroundColor = ... label.textColor =
... label.font = ... label.text = text ... label.sizeToFit() label.frame.size.height += ceil(abs(label.font.descender * 2)) kk@realm.io ্ԼʹDescentΛิ͏
kk@realm.io ্ԼʹDescentΛิ͏
kk@realm.io ্ԼʹDescentΛิ͏
kk@realm.io ΦϦδφϧͱൺֱ
• ώϥΪϊΛ໌ࣔతʹࢦఆ͠ͳ͍ • γεςϜϑΥϯτΛ͏ • σβΠϯࢦࣔॻͳͲͰɺώϥΪϊ͍͍ͨͯγε ςϜϑΥϯτΛҙਤ͍ͯ͠Δͣ • தࠃޠ༻ϑΥϯτʹϑΥʔϧόοΫͨ͘͠ͳ͍Մ ೳੑ
• ώϥΪϊΛࢦఆ͢Δ߹ɺΞϧϑΝϕοτʹؾΛ ͚ͭΔ kk@realm.io ώϥΪϊͷϝτϦΫεʹҙ
kk@realm.io Tips: ຊޠϑΥϯτʹϑΥʔϧόοΫͤ͞Δ let attributes = [ NSFontAttributeName: font, kCTLanguageAttributeName
as String: "ja", ... ]
αΠζͷܭࢉ kk@realm.io
let size = CGSize(width: label.bounds.width, height: CGFloat.max) let boundingRect =
NSString(string: text).boundingRectWithSize(size, options: [.UsesLineFragmentOrigin], attributes: [NSFontAttributeName: font], context: nil) kk@realm.io ඳըαΠζΛಘΔ
kk@realm.io ඳըαΠζΛಘΔ
UITextView kk@realm.io
kk@realm.io UITextViewΛී௨ʹ͏
kk@realm.io UITextViewΛී௨ʹ͏ UIFont(name: "HiraginoSans-W3", size: 32) UIFont.systemFontOfSize(32)
kk@realm.io ඳըαΠζ
kk@realm.io ඳըαΠζ
kk@realm.io σϑΥϧτͷϚʔδϯ
σϑΥϧτͷϚʔδϯ textView.textContainer.lineFragmentPadding textView.textContainerInset UIEdgeInsets(top: 8.0, left: 0.0, bottom: 8.0, right:
0.0) 5.0 kk@realm.io
kk@realm.io ώϥΪϊΛࢦఆͨ͠߹ font.leading
σϑΥϧτͷελΠϧΛϦηοτ͢Δ kk@realm.io
let textView = UITextView(frame: view.bounds) ... textView.textContainerInset = UIEdgeInsetsZero textView.sizeToFit()
kk@realm.io textContainerInsetΛऔΓআ͘
let textView = UITextView(frame: view.bounds) ... textView.textContainerInset = UIEdgeInsetsZero textView.sizeToFit()
kk@realm.io textContainerInsetΛऔΓআ͘
kk@realm.io textContainerInsetΛऔΓআ͘
let textView = UITextView(frame: view.bounds) ... textView.textContainer.lineFragmentPadding = 0 textView.sizeToFit()
kk@realm.io lineFragmentPaddingΛऔΓআ͘
let textView = UITextView(frame: view.bounds) ... textView.textContainer.lineFragmentPadding = 0 textView.sizeToFit()
kk@realm.io lineFragmentPaddingΛऔΓআ͘
kk@realm.io lineFragmentPaddingΛऔΓআ͘
let size = CGSize(width: textView.bounds.width, height: CGFloat.max) let boundingRect =
NSString(string: text).boundingRectWithSize(size, options: [.UsesLineFragmentOrigin], attributes: [NSFontAttributeName: font], context: nil) kk@realm.io ඳըαΠζΛಘΔ
kk@realm.io ඳըαΠζΛಘΔ
let textView = UITextView(frame: view.bounds) ... textView.layoutManager.usesFontLeading = false textView.sizeToFit()
kk@realm.io font.leadingΛऔΓআ͘
let textView = UITextView(frame: view.bounds) ... textView.layoutManager.usesFontLeading = false textView.sizeToFit()
kk@realm.io font.leadingΛऔΓআ͘
kk@realm.io font.leadingΛऔΓআ͘
let size = CGSize(width: textView.bounds.width, height: CGFloat.max) let boundingRect =
NSString(string: text).boundingRectWithSize(size, options: [.UsesLineFragmentOrigin, .UsesFontLeading], attributes: [NSFontAttributeName: font], context: nil) kk@realm.io ʢผղʣfont.leadingΛؚΊͯܭࢉ͢Δ
kk@realm.io ʢผղʣfont.leadingΛؚΊͯܭࢉ͢Δ
kk@realm.io ʢผղʣfont.leadingΛؚΊͯܭࢉ͢Δ
kk@realm.io textView.textContainerInset = UIEdgeInsetsZero textView.textContainer.lineFragmentPadding = 0 textView.layoutManager.usesFontLeading = false
σϑΥϧτελΠϧͷϦηοτ
͞·͟·ͳελΠϧʹରԠ͢Δ kk@realm.io
kk@realm.io ߦؒͷมߋ
NSAttributedString kk@realm.io
NSParagraphStyle kk@realm.io
let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.minimumLineHeight = ceil(font.lineHeight) paragraphStyle.maximumLineHeight = ceil(font.lineHeight)
paragraphStyle.lineSpacing = 8 let attributes = [ NSFontAttributeName: font, NSForegroundColorAttributeName: UIColor(...), NSParagraphStyleAttributeName: paragraphStyle, ] let attributedText = NSAttributedString(string: text, attributes: attributes) textView.attributedText = attributedText kk@realm.io NSAttributedString
let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.minimumLineHeight = ceil(font.lineHeight) paragraphStyle.maximumLineHeight = ceil(font.lineHeight)
paragraphStyle.lineSpacing = 8 let attributes = [ NSFontAttributeName: font, NSForegroundColorAttributeName: UIColor(...), NSParagraphStyleAttributeName: paragraphStyle, ] let attributedText = NSAttributedString(string: text, attributes: attributes) textView.attributedText = attributedText kk@realm.io NSAttributedString
kk@realm.io ߦؒͷมߋ
kk@realm.io ߦؒͷมߋ
let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.minimumLineHeight = ceil(font.lineHeight) paragraphStyle.maximumLineHeight = ceil(font.lineHeight)
paragraphStyle.lineSpacing = 8 kk@realm.io min/maxLineHeight
kk@realm.io min/maxLineHeight
kk@realm.io minimumLineHeight
kk@realm.io maximumLineHeight
NSAttributedStringΛ׆༻͢Δ kk@realm.io
kk@realm.io ͞ΒʹߦؒΛ͘
kk@realm.io ͞ΒʹߦؒΛ͘
kk@realm.io Օॻ͖
·ͱΊ • iOS 7Ҏ߱ͷςΩετϨΠΞτɺ͍͔ʹ ΩϨΠͳNSAttributedStringΛ࡞Δ͔ • λΠϙάϥϑΟͷجૅΛΖ͏ • ϑΥϯτʹώϥΪϊΛࢦఆ͢Δͱ͖ҙ •
Ͱ͖Δ͚ͩγεςϜϑΥϯτΛ͓͏ kk@realm.io
Questions? Katsuma Kishikawa kk@realm.io www.realm.io/jp @k_katsumi