Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
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.9k
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
愛される翻訳の秘訣
kishikawakatsumi
1
310
Private APIの呼び出し方
kishikawakatsumi
3
930
iOSでSVG画像を扱う
kishikawakatsumi
0
210
Build your own WebP codec in Swift
kishikawakatsumi
2
1.3k
iOSDC 2024 SMBファイル共有をSwiftで実装する
kishikawakatsumi
1
280
Enhancing Applications with Accessibility API
kishikawakatsumi
3
4.9k
Mastering SwiftSyntax
kishikawakatsumi
4
7.2k
My SwiftData Review
kishikawakatsumi
7
1.5k
Swift Expression Macros: a practical introduction
kishikawakatsumi
3
2k
Other Decks in Programming
See All in Programming
Cap'n Webについて
yusukebe
0
130
WebRTC、 綺麗に見るか滑らかに見るか
sublimer
1
160
MAP, Jigsaw, Code Golf 振り返り会 by 関東Kaggler会|Jigsaw 15th Solution
hasibirok0
0
230
ViewファーストなRailsアプリ開発のたのしさ
sugiwe
0
430
AtCoder Conference 2025「LLM時代のAHC」
imjk
1
160
まだ間に合う!Claude Code元年をふりかえる
nogu66
5
630
CSC509 Lecture 14
javiergs
PRO
0
220
生成AIを利用するだけでなく、投資できる組織へ
pospome
0
240
CSC305 Lecture 17
javiergs
PRO
0
340
251126 TestState APIってなんだっけ?Step Functionsテストどう変わる?
east_takumi
0
310
tparseでgo testの出力を見やすくする
utgwkk
1
190
AIコーディングエージェント(NotebookLM)
kondai24
0
170
Featured
See All Featured
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Navigating Team Friction
lara
191
16k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Automating Front-end Workflow
addyosmani
1371
200k
Facilitating Awesome Meetings
lara
57
6.7k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Site-Speed That Sticks
csswizardry
13
990
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Code Reviewing Like a Champion
maltzj
527
40k
RailsConf 2023
tenderlove
30
1.3k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.1k
Transcript
Handling rich text in Swift iOSDC Japan 2016 Katsumi Kishikawa
[email protected]
Katsumi Kishikawa Realm Inc.
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
Agenda ˖ J04ךذؗأزٖ؎،ؐزחאְג ˖ ة؎هؚٓؿ؍ך㛇燉 ˖ 5FYU,JUך㛇燉ה䘔欽
[email protected]
iOS 7Ҏ߱ͷςΩετϨΠΞτ
[email protected]
TextKit
[email protected]
TextKitͱ ˖ 넝鸞זٌتٝذؗأزٖ؎،ؐز٥ٖٝت ؚٔٝؒٝآٝ ˖ $PSF5FYUד⡲גְ ˖ 6*,JUהך窟さ
[email protected]
https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/CustomTextProcessing/CustomTextProcessing.html
UILabel
[email protected]
[email protected]
UILabelΛී௨ʹ͏
[email protected]
ώϥΪϊͱγεςϜϑΥϯτ UIFont(name: "HiraginoSans-W3", size: 32) UIFont.systemFontOfSize(32)
[email protected]
ώϥΪϊͱγεςϜϑΥϯτ
[email protected]
ώϥΪϊͱγεςϜϑΥϯτ
[email protected]
General Header
[email protected]
ΞϧϑΝϕοτΛؚ·ͳ͍߹
ߦͷߴ͞ԿͰܾ·Δ͔
[email protected]
[email protected]
Font metrics https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html
[email protected]
Font metrics https://developer.apple.com/library/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html
[email protected]
Font metrics
[email protected]
Font metrics Baseline X-Height Cap height Ascent Descent
[email protected]
ώϥΪϊಛघͳϝτϦΫεΛ࣋ͭ
[email protected]
ʢࢀߟʣ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))
[email protected]
্ԼʹDescentΛิ͏
[email protected]
্ԼʹDescentΛิ͏
[email protected]
্ԼʹDescentΛิ͏
[email protected]
ΦϦδφϧͱൺֱ
• ώϥΪϊΛ໌ࣔతʹࢦఆ͠ͳ͍ • γεςϜϑΥϯτΛ͏ • σβΠϯࢦࣔॻͳͲͰɺώϥΪϊ͍͍ͨͯγε ςϜϑΥϯτΛҙਤ͍ͯ͠Δͣ • தࠃޠ༻ϑΥϯτʹϑΥʔϧόοΫͨ͘͠ͳ͍Մ ೳੑ
• ώϥΪϊΛࢦఆ͢Δ߹ɺΞϧϑΝϕοτʹؾΛ ͚ͭΔ
[email protected]
ώϥΪϊͷϝτϦΫεʹҙ
[email protected]
Tips: ຊޠϑΥϯτʹϑΥʔϧόοΫͤ͞Δ let attributes = [ NSFontAttributeName: font, kCTLanguageAttributeName
as String: "ja", ... ]
αΠζͷܭࢉ
[email protected]
let size = CGSize(width: label.bounds.width, height: CGFloat.max) let boundingRect =
NSString(string: text).boundingRectWithSize(size, options: [.UsesLineFragmentOrigin], attributes: [NSFontAttributeName: font], context: nil)
[email protected]
ඳըαΠζΛಘΔ
[email protected]
ඳըαΠζΛಘΔ
UITextView
[email protected]
[email protected]
UITextViewΛී௨ʹ͏
[email protected]
UITextViewΛී௨ʹ͏ UIFont(name: "HiraginoSans-W3", size: 32) UIFont.systemFontOfSize(32)
[email protected]
ඳըαΠζ
[email protected]
ඳըαΠζ
[email protected]
σϑΥϧτͷϚʔδϯ
σϑΥϧτͷϚʔδϯ textView.textContainer.lineFragmentPadding textView.textContainerInset UIEdgeInsets(top: 8.0, left: 0.0, bottom: 8.0, right:
0.0) 5.0
[email protected]
[email protected]
ώϥΪϊΛࢦఆͨ͠߹ font.leading
σϑΥϧτͷελΠϧΛϦηοτ͢Δ
[email protected]
let textView = UITextView(frame: view.bounds) ... textView.textContainerInset = UIEdgeInsetsZero textView.sizeToFit()
[email protected]
textContainerInsetΛऔΓআ͘
let textView = UITextView(frame: view.bounds) ... textView.textContainerInset = UIEdgeInsetsZero textView.sizeToFit()
[email protected]
textContainerInsetΛऔΓআ͘
[email protected]
textContainerInsetΛऔΓআ͘
let textView = UITextView(frame: view.bounds) ... textView.textContainer.lineFragmentPadding = 0 textView.sizeToFit()
[email protected]
lineFragmentPaddingΛऔΓআ͘
let textView = UITextView(frame: view.bounds) ... textView.textContainer.lineFragmentPadding = 0 textView.sizeToFit()
[email protected]
lineFragmentPaddingΛऔΓআ͘
[email protected]
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)
[email protected]
ඳըαΠζΛಘΔ
[email protected]
ඳըαΠζΛಘΔ
let textView = UITextView(frame: view.bounds) ... textView.layoutManager.usesFontLeading = false textView.sizeToFit()
[email protected]
font.leadingΛऔΓআ͘
let textView = UITextView(frame: view.bounds) ... textView.layoutManager.usesFontLeading = false textView.sizeToFit()
[email protected]
font.leadingΛऔΓআ͘
[email protected]
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)
[email protected]
ʢผղʣfont.leadingΛؚΊͯܭࢉ͢Δ
[email protected]
ʢผղʣfont.leadingΛؚΊͯܭࢉ͢Δ
[email protected]
ʢผղʣfont.leadingΛؚΊͯܭࢉ͢Δ
[email protected]
textView.textContainerInset = UIEdgeInsetsZero textView.textContainer.lineFragmentPadding = 0 textView.layoutManager.usesFontLeading = false
σϑΥϧτελΠϧͷϦηοτ
͞·͟·ͳελΠϧʹରԠ͢Δ
[email protected]
[email protected]
ߦؒͷมߋ
NSAttributedString
[email protected]
NSParagraphStyle
[email protected]
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
[email protected]
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
[email protected]
NSAttributedString
[email protected]
ߦؒͷมߋ
[email protected]
ߦؒͷมߋ
let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.minimumLineHeight = ceil(font.lineHeight) paragraphStyle.maximumLineHeight = ceil(font.lineHeight)
paragraphStyle.lineSpacing = 8
[email protected]
min/maxLineHeight
[email protected]
min/maxLineHeight
[email protected]
minimumLineHeight
[email protected]
maximumLineHeight
NSAttributedStringΛ׆༻͢Δ
[email protected]
[email protected]
͞ΒʹߦؒΛ͘
[email protected]
͞ΒʹߦؒΛ͘
[email protected]
Օॻ͖
·ͱΊ • iOS 7Ҏ߱ͷςΩετϨΠΞτɺ͍͔ʹ ΩϨΠͳNSAttributedStringΛ࡞Δ͔ • λΠϙάϥϑΟͷجૅΛΖ͏ • ϑΥϯτʹώϥΪϊΛࢦఆ͢Δͱ͖ҙ •
Ͱ͖Δ͚ͩγεςϜϑΥϯτΛ͓͏
[email protected]
Questions? Katsuma Kishikawa
[email protected]
www.realm.io/jp @k_katsumi