Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
TextKitで行うテキスト装飾パターン/Text decoration pattern wi...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
株式会社ヌーラボ
PRO
October 30, 2019
Technology
900
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
TextKitで行うテキスト装飾パターン/Text decoration pattern with TextKit
株式会社ヌーラボ
PRO
October 30, 2019
More Decks by 株式会社ヌーラボ
See All by 株式会社ヌーラボ
配布資料_ヌーラボの情シスがおすすめする_問い合わせ対応を削減するBacklog活用術.pdf
nulabinc
PRO
0
94
Bits Agent Builder の⼊⾨と活⽤事例
nulabinc
PRO
0
2.7k
Getting Started with Bits Agent Builder: Real-World Use Cases
nulabinc
PRO
0
79
The_Evolution_of_Bits_AI_SRE.pdf
nulabinc
PRO
0
410
進化するBits AI SREと私と組織
nulabinc
PRO
4
1.2k
実践 Datadog MCP Server
nulabinc
PRO
4
970
全社横断PjM⽀援チーム “PEaS”の取り組みと プロジェクトマネジメント でのAI活⽤について
nulabinc
PRO
0
240
Datadog の RBAC のすべて
nulabinc
PRO
4
970
Datadog Live Tokyo 2025登壇資料
nulabinc
PRO
0
240
Other Decks in Technology
See All in Technology
C#未経験の僕がAIに読めるコードを書かせるまで
maguroalternative
0
210
白金鉱業Meetup Vol.25 アウトカムが二値のデータに対するCausal Impact
brainpadpr
0
270
事業課題から技術的負債に向き合う
sansantech
PRO
2
2.2k
すぐできる衛星通信対応 あとは山奥に行くだけ
tatetate55
0
140
Issue 駆動でスペシャリストの意図を届ける、AI 実装のアクセシビリティ向上
thkt
0
130
負債のメタファと2026年 / Debt Metaphor in Agentic Engineering Age 202609 Edition
twada
PRO
10
4.8k
株式会社シーエーシー エンジニア向け会社紹介資料
cac
0
57k
Oracle Cloud Network Path Analyzerを試してみた/I Tried Out Oracle Cloud Network Path Analyzer
masakiokuda
1
110
開発投資の期待値を上げるプロダクトロードマップづくり ~プロダクトエンジニアが越境して事業を伸ばす~
kekekenta
1
240
`t*(42&t>>10)`だけで音楽が鳴る、Swiftで実装するBytebeat / iOSDC Japan 2026
yutailang0119
0
130
Deployment の 先にある AI Agent 基盤 - kagent vNext、Agent Substrate、Hermes から読み解く Agent Runtime の現在地 / k8s-matsuri-2-ai-agent-platform-amsy810
masayaaoyama
4
700
.NET WebAssemblyで実現するクライアントサイドAI推論:NuGetからViteまで、2つのエコシステムを繋ぐビルド戦略
yamachu
0
410
Featured
See All Featured
WENDY [Excerpt]
tessaabrams
14
39k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
850
Git: the NoSQL Database
bkeepers
PRO
432
67k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
3
4.3k
Between Models and Reality
mayunak
4
460
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.5k
Agile that works and the tools we love
rasmusluckow
331
22k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
420
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
880
Navigating Weather and Climate Data
rabernat
0
520
Heart Work Chapter 1 - Part 1
lfama
PRO
10
36k
A Tale of Four Properties
chriscoyier
163
24k
Transcript
TextKitͰߦ͏ςΩετ ০ύλʔϯ at ୈ10ճ HAKATA.swift ~ԬͰSwiftͷษڧձ~ 1 By Taichiro Yoshida
(@dataich)
ϓϩϑΟʔϧ • ٢ాଠҰ @dataich • Swift/Scala • גࣜձࣾψʔϥϘॴଐ • WebαʔϏε
TypetalkΛ։ൃɾӡ༻த • ΠΠϨ 2 By Taichiro Yoshida (@dataich)
એ ! 3 By Taichiro Yoshida (@dataich)
Backlog 4 By Taichiro Yoshida (@dataich)
Cacoo 5 By Taichiro Yoshida (@dataich)
Typetalk 6 By Taichiro Yoshida (@dataich)
ࠓ͓͢Δ͜ͱ • TextKitͰߦ͏ςΩετ০ύλʔϯ • TextKitͱ • ඪ४Ͱఏڙ͞Ε͍ͯΔ০ • ຊ •
ඪ४Ͱఏڙ͞Ε͍ͯͳ͍০ • ࣮ύλʔϯ • ·ͱΊ 7 By Taichiro Yoshida (@dataich)
ιʔείʔυ dataich/TextKitSample 8 By Taichiro Yoshida (@dataich)
TextKitͱ TextKit | Apple Developer Documentation • ςΩετͷϨΠΞτΛίϯτϩʔϧ͢Δ༷ʑͳΫϥεͷू·Γ • NSAttributedString
• NSTextStorage (NSMutableAttributedString) • NSLayoutManager • NSTextContainer • UILabelɺUITextViewͳͲΛ͍ͬͯΕࣗવͱͦͷҰ෦Λ͍ͬͯΔ 9 By Taichiro Yoshida (@dataich)
ग़య - Text Programming Guide for iOS 10 By Taichiro
Yoshida (@dataich)
NSAttributedString • จࣈྻ • จࣈྻͷൣғͱͦͷଐੑใʢݟͨϦϯΫͳͲʣͷϦετ Λ࣋ͭ 11 By Taichiro Yoshida
(@dataich)
NSTextStorage (NSMutableAttributedString) • TextKitͰͷॏཁͳετϨʔδϝΧχζϜ • NSMutableAttributedStringͷαϒΫϥεʹͳ͍ͬͯΔ • ςΩετଐੑใʹมߋ͕Ճ͑ΒΕΔͱޙड़͢Δ NSLayoutManagerʹ௨͢Δ 12
By Taichiro Yoshida (@dataich)
NSTextContainer • ςΩετΛදࣔ͢ΔίϯςφͷใΛ࣋ͭ • ࠲ඪͱܗঢ়Λ࣋ͪɺͲ͜ʹςΩετΛͲ͏ද͖͔ࣔ͢Λఆٛ ͢Δ • Ͳ͜Ͱվߦ͖͢ͳͷ͔ͳͲ • αϒΫϥεΛఆٛͯ͠ɺಠࣗͷίϯςφΛ࣮Մೳ
• ྫʣ ପԁܗͷςΩετίϯςφ 13 By Taichiro Yoshida (@dataich)
NSLayoutManager • NSTextStorage͕࣋ͭจࣈྻΛϨΠΞτ͠දࣔ͢Δ • NSTextStorageͷมߋ௨Λड͚औΓඳը • UnicodeͷจࣈΛάϦϑʹϚοϓ͠ɺͦΕΛNSTextContainerʹ ηοτ • ߋʹͦͷNSTextContainerΛUITextViewͳͲʹηοτ
• ඳը͞Ε͍ͯΔάϦϑͷ࠲ඪΛ͍ͬͯΔ 14 By Taichiro Yoshida (@dataich)
ඪ४Ͱఏڙ͞Ε͍ͯΔ ০ 15 By Taichiro Yoshida (@dataich)
ྫ let text = """ ԬͷiOSΤϯδχΞୡ͕ओ࠵͢Δɺ ϓϩάϥϛϯάݴޠ Swift ͱͦͷपลٕज़ͷษڧձͰ͢ɻ ൃలΛଓ͚Δ
Swift ͱͦͷपลٕज़ͷಈΛ͍ɺ ॳ৺ऀ/্ڃऀ/एஉঁΛΘͣɺใަͷͱͯ͠ ػೳ͢Δ͜ͱΛతͱ͍ͯ͠·͢ɻ """ 16 By Taichiro Yoshida (@dataich)
NSAttributedString.Key .foregroundColor - จࣈ৭ 17 By Taichiro Yoshida (@dataich)
NSAttributedString.Key .foregroundColor - จࣈ৭ let attributedString = NSMutableAttributedString(string: text) attributedString.setAttributes(
[NSAttributedString.Key.foregroundColor : UIColor.blue], range: NSRange(location: 18, length: 15)) 18 By Taichiro Yoshida (@dataich)
NSAttributedString.Key .backgroundColor - എܠ৭ 19 By Taichiro Yoshida (@dataich)
NSAttributedString.Key .backgroundColor - എܠ৭ let attributedString = NSMutableAttributedString(string: text) attributedString.setAttributes(
[NSAttributedString.Key.backgroundColor : UIColor.lightGray], range: NSRange(location: 18, length: 15)) 20 By Taichiro Yoshida (@dataich)
NSAttributedString.Key .font - ϑΥϯτ 21 By Taichiro Yoshida (@dataich)
NSAttributedString.Key .font - ϑΥϯτ let attributedString = NSMutableAttributedString(string: text) attributedString.setAttributes(
[NSAttributedString.Key.font : UIFont.systemFont(ofSize: 14)], range: NSRange(location: 0, length: text.count)) attributedString.setAttributes( [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 14)], range: NSRange(location: 18, length: 15)) 22 By Taichiro Yoshida (@dataich)
ͦͷଞ • NSAttributedString.Key.paragraphStyle • NSAttributedString.Key.underlineStyle • NSAttributedString.Key.shadow NSAttributedString.Key - NSAttributedString
| Apple Developer Documentation 23 By Taichiro Yoshida (@dataich)
ඪ४Ͱఏڙ͞Ε͍ͯͳ ͍০ 24 By Taichiro Yoshida (@dataich)
ྫ: ΠϯϥΠϯίʔυ • എܠΛؙ֯ʹ͍ͨ͠ • എܠʹϘʔμʔΛ͚͍ͨ 25 By Taichiro Yoshida
(@dataich)
ྫ: ίʔυ • จࣈྻ͚ͩ͡Όͳ͘ෳߦશମͷഎܠΛΧελϜ͍ͨ͠ 26 By Taichiro Yoshida (@dataich)
ྫ: Ҿ༻ • ߦ಄ʹॎઢΛҾ͖͍ͨ 27 By Taichiro Yoshida (@dataich)
࣮ྫ 28 By Taichiro Yoshida (@dataich)
ΠϯϥΠϯίʔυ 29 By Taichiro Yoshida (@dataich)
1. NSAttributedStringʹΧελϜଐੑΛՃ͢Δ struct InlineCodeSample { // 1. ΧελϜଐੑͷΩʔΛఆٛ static let
key = NSAttributedString.Key(rawValue: "InlineCode") var attributedString: NSAttributedString { ... let attributedString = NSMutableAttributedString(string: text) // 2. ൣғΛࢦఆͯ͠ΧελϜଐੑΛઃఆ attributedString.setAttributes([Self.key : UIColor.lightGray], range: NSRange(location: 18, length: 23)) return attributedString } } 30 By Taichiro Yoshida (@dataich)
2. NSLayoutManagerΛܧঝͨ͠ΫϥεΛ࡞Δ class CustomLayoutManager: NSLayoutManager { //ɹϨΠΞτʹؔΘΔॲཧΛ࣮͢Δ } ... let
textStorage = NSTextStorage() let layoutManager = CustomLayoutManager() let textContainer = NSTextContainer() layoutManager.addTextContainer(textContainer) textStorage.addLayoutManager(layoutManager) textView = UITextView(frame: .zero, textContainer: textContainer) 31 By Taichiro Yoshida (@dataich)
3. CustomLayoutManagerͰඞཁͳඳըϝιουΛΦʔόʔϥΠυ ͢Δ class CustomLayoutManager: NSLayoutManager { // എܠͷඳըΛߦ͏ॲཧ override
func drawBackground(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) { super.drawBackground(forGlyphRange: glyphsToShow, at: origin) drawInlineCode(forGlyphRange: glyphsToShow, at: origin) } func drawInlineCode(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) { // ΠϯϥΠϯίʔυʹؔΘΔॲཧΛ࣮͢Δ } } 32 By Taichiro Yoshida (@dataich)
4. ΧελϜଐੑΛ࣋ͭจࣈྻͷൣғΛ୳͢ func drawInlineCode(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) {
let range = characterRange( forGlyphRange: glyphsToShow, actualGlyphRange: nil) textStorage?.enumerateAttribute( InlineCodeSample.key, in: range, options: []) { (color, range, _) in // ΧελϜଐੑInlineCodeʹؔΘΔॲཧΛ࣮͢Δ }) } 33 By Taichiro Yoshida (@dataich)
5. ΧελϜଐੑΛ࣋ͭจࣈྻͷάϦϑ͕දࣔ͞ΕΔCGRectΛऔಘ ͯ͠ඳըॲཧΛߦ͏ • enumerateEnclosingRectsΛ͏ 34 By Taichiro Yoshida (@dataich)
5. ΧελϜଐੑΛ࣋ͭจࣈྻͷάϦϑ͕දࣔ͞ΕΔCGRectΛऔಘ ͯ͠ඳըॲཧΛߦ͏ let glyphRange = self.glyphRange(forCharacterRange: range, actualCharacterRange: nil)
self.enumerateEnclosingRects( forGlyphRange: glyphRange, withinSelectedGlyphRange: glyphRange, in: container) { (rect, _) in // άϦϑ͕ඳը͞Ε͍ͯΔCGRect͕औಘͰ͖ΔͷͰ // UIBezierPathͳͲΛͬͯഎܠϘʔμʔΛඳը͢Δ } 35 By Taichiro Yoshida (@dataich)
ίʔυ • جຊతʹΠϯϥΠϯίʔυͱಉ͡ 36 By Taichiro Yoshida (@dataich)
• enumerateEnclosingRectsͰͳ͘enumerateLineFragments Λ͏ 37 By Taichiro Yoshida (@dataich)
enumerateLineFragmentsͰߦྖҬͷCGRectΛऔಘ self.enumerateLineFragments( forGlyphRange: glyphRange) { (rect, usedRect, textContainer, glyphRange, stop)
in // άϦϑ͕ඳը͞Ε͍ͯΔߦͷCGRect͕औಘͰ͖ΔͷͰ // ෳߦͷߴ͞Λܭࢉ͢ΔͳͲ͢Δ } • enumerateEnclosingRectsάϦϑ͕දࣔ͞Ε͍ͯΔ֤ྖҬͷCGRectΛྻ ڍ • enumerateLineFragmentsάϦϑ͕දࣔ͞Ε͍ͯΔߦྖҬͷCGRectΛྻڍ • boundingRectશͯͷάϦϑ͕ऩ·ΔྖҬͷCGRect1ͭ 38 By Taichiro Yoshida (@dataich)
boundingRect 39 By Taichiro Yoshida (@dataich)
Ҿ༻ • ίʔυͱ΄΅ಉ͡ͰඳըͷίʔυΛม͑ΔͷΈ 40 By Taichiro Yoshida (@dataich)
ͦͷଞ • എܠҎ֎ͷ߹ΦʔόϥΠυ͖͢ϝιου͕͋ΔΈ͍ͨ ʢࢼͯ͠ͳ͍ʣ • drawGlyphs • drawStrikethrough • drawUnderline
41 By Taichiro Yoshida (@dataich)
·ͱΊ • NSAttributedStringʹΧελϜଐੑΛՃ͢Δ • NSLayoutManagerΛܧঝͨ͠ΫϥεΛ࡞Δ • CustomLayoutManagerͰඞཁͳඳըϝιουΛΦʔόʔϥΠυ͢Δ • ΧελϜଐੑΛ࣋ͭจࣈྻͷൣғΛ୳͢ •
ΧελϜଐੑΛ࣋ͭจࣈྻͷάϦϑ͕දࣔ͞ΕΔCGRectΛऔಘͯ͠ඳ ըॲཧΛߦ͏ • TextKitཧղ͢Δͱָ͍͠ʂ 42 By Taichiro Yoshida (@dataich)
ࢀߟ • TextKitΛϚελʔ͠ɺࢥ͍௨ΓʹจࣈΛϨΠΞτ͢Δ • TextKitʹΑΔςΩετϨΠΞτ 43 By Taichiro Yoshida (@dataich)
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ 44 By Taichiro Yoshida (@dataich)