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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Kishikawa Katsumi
August 20, 2016
Programming
17
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
Automatic Grammar Agreementと Markdown Extended Attributes について
kishikawakatsumi
0
180
愛される翻訳の秘訣
kishikawakatsumi
3
380
Private APIの呼び出し方
kishikawakatsumi
3
970
iOSでSVG画像を扱う
kishikawakatsumi
0
210
Build your own WebP codec in Swift
kishikawakatsumi
2
1.6k
iOSDC 2024 SMBファイル共有をSwiftで実装する
kishikawakatsumi
1
290
Enhancing Applications with Accessibility API
kishikawakatsumi
3
5.1k
Mastering SwiftSyntax
kishikawakatsumi
4
7.4k
My SwiftData Review
kishikawakatsumi
7
1.5k
Other Decks in Programming
See All in Programming
今から始めるClaude Code超入門
448jp
6
7.1k
dchart: charts from deck markup
ajstarks
3
980
AIフル活用時代だからこそ学んでおきたい働き方の心得
shinoyu
0
120
Oxlintはいいぞ
yug1224
5
1.2k
16年目のピクシブ百科事典を支える最新の技術基盤 / The Modern Tech Stack Powering Pixiv Encyclopedia in its 16th Year
ahuglajbclajep
5
950
大規模Cloud Native環境におけるFalcoの運用
owlinux1000
0
260
CSC307 Lecture 06
javiergs
PRO
0
680
例外処理とどう使い分ける?Result型を使ったエラー設計 #burikaigi
kajitack
16
5.9k
re:Invent 2025 トレンドからみる製品開発への AI Agent 活用
yoskoh
0
710
CSC307 Lecture 02
javiergs
PRO
1
770
AIエージェント、”どう作るか”で差は出るか? / AI Agents: Does the "How" Make a Difference?
rkaga
4
1.9k
KIKI_MBSD Cybersecurity Challenges 2025
ikema
0
1.3k
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
1.8k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
810
Stop Working from a Prison Cell
hatefulcrawdad
273
21k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
1
110
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.7k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
51
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Raft: Consensus for Rubyists
vanstee
141
7.3k
Design in an AI World
tapps
0
140
Heart Work Chapter 1 - Part 1
lfama
PRO
5
35k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
9.8k
HDC tutorial
michielstock
1
330
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