Slide 1

Slide 1 text

TextKitͰߦ͏ςΩετ ૷০ύλʔϯ at ୈ10ճ HAKATA.swift ~෱ԬͰSwiftͷษڧձ~ 1 By Taichiro Yoshida (@dataich)

Slide 2

Slide 2 text

ϓϩϑΟʔϧ • ٢ాଠҰ࿠ @dataich • Swift/Scala • גࣜձࣾψʔϥϘॴଐ • WebαʔϏε TypetalkΛ։ൃɾӡ༻த • ΢ΠΠϨ 2 By Taichiro Yoshida (@dataich)

Slide 3

Slide 3 text

એ఻ ! 3 By Taichiro Yoshida (@dataich)

Slide 4

Slide 4 text

Backlog 4 By Taichiro Yoshida (@dataich)

Slide 5

Slide 5 text

Cacoo 5 By Taichiro Yoshida (@dataich)

Slide 6

Slide 6 text

Typetalk 6 By Taichiro Yoshida (@dataich)

Slide 7

Slide 7 text

ࠓ೔͓࿩͢Δ͜ͱ • TextKitͰߦ͏ςΩετ૷০ύλʔϯ • TextKitͱ͸ • ඪ४Ͱఏڙ͞Ε͍ͯΔ૷০ • ຊ୊ • ඪ४Ͱఏڙ͞Ε͍ͯͳ͍૷০ • ࣮૷ύλʔϯ • ·ͱΊ 7 By Taichiro Yoshida (@dataich)

Slide 8

Slide 8 text

ιʔείʔυ dataich/TextKitSample 8 By Taichiro Yoshida (@dataich)

Slide 9

Slide 9 text

TextKitͱ͸ TextKit | Apple Developer Documentation • ςΩετͷϨΠΞ΢τΛίϯτϩʔϧ͢Δ༷ʑͳΫϥεͷू·Γ • NSAttributedString • NSTextStorage (NSMutableAttributedString) • NSLayoutManager • NSTextContainer • UILabelɺUITextViewͳͲΛ࢖͍ͬͯΕ͹ࣗવͱͦͷҰ෦Λ࢖͍ͬͯΔ 9 By Taichiro Yoshida (@dataich)

Slide 10

Slide 10 text

ग़య - Text Programming Guide for iOS 10 By Taichiro Yoshida (@dataich)

Slide 11

Slide 11 text

NSAttributedString • จࣈྻ • จࣈྻͷൣғͱͦͷଐੑ৘ใʢݟͨ໨΍ϦϯΫͳͲʣͷϦετ Λ࣋ͭ 11 By Taichiro Yoshida (@dataich)

Slide 12

Slide 12 text

NSTextStorage (NSMutableAttributedString) • TextKitͰͷॏཁͳετϨʔδϝΧχζϜ • NSMutableAttributedStringͷαϒΫϥεʹͳ͍ͬͯΔ • ςΩετ΍ଐੑ৘ใʹมߋ͕Ճ͑ΒΕΔͱޙड़͢Δ NSLayoutManagerʹ௨஌͢Δ 12 By Taichiro Yoshida (@dataich)

Slide 13

Slide 13 text

NSTextContainer • ςΩετΛදࣔ͢Δίϯςφͷ৘ใΛ࣋ͭ • ࠲ඪͱܗঢ়Λ࣋ͪɺͲ͜ʹςΩετΛͲ͏දࣔ͢΂͖͔Λఆٛ ͢Δ • Ͳ͜Ͱվߦ͢΂͖ͳͷ͔ͳͲ • αϒΫϥεΛఆٛͯ͠ɺಠࣗͷίϯςφΛ࣮૷Մೳ • ྫʣ ପԁܗͷςΩετίϯςφ 13 By Taichiro Yoshida (@dataich)

Slide 14

Slide 14 text

NSLayoutManager • NSTextStorage͕࣋ͭจࣈྻΛϨΠΞ΢τ͠දࣔ͢Δ • NSTextStorageͷมߋ௨஌Λड͚औΓඳը • UnicodeͷจࣈΛάϦϑʹϚοϓ͠ɺͦΕΛNSTextContainerʹ ηοτ • ߋʹͦͷNSTextContainerΛUITextViewͳͲʹηοτ • ඳը͞Ε͍ͯΔάϦϑͷ࠲ඪΛ஌͍ͬͯΔ 14 By Taichiro Yoshida (@dataich)

Slide 15

Slide 15 text

ඪ४Ͱఏڙ͞Ε͍ͯΔ ૷০ 15 By Taichiro Yoshida (@dataich)

Slide 16

Slide 16 text

ྫ let text = """ ෱ԬͷiOSΤϯδχΞୡ͕ओ࠵͢Δɺ ϓϩάϥϛϯάݴޠ Swift ͱͦͷपลٕज़ͷษڧձͰ͢ɻ ൃలΛଓ͚Δ Swift ͱͦͷपลٕज़ͷಈ޲Λ௥͍ɺ ॳ৺ऀ/্ڃऀ/࿝एஉঁΛ໰Θͣɺ৘ใަ׵ͷ৔ͱͯ͠ ػೳ͢Δ͜ͱΛ໨తͱ͍ͯ͠·͢ɻ """ 16 By Taichiro Yoshida (@dataich)

Slide 17

Slide 17 text

NSAttributedString.Key .foregroundColor - จࣈ৭ 17 By Taichiro Yoshida (@dataich)

Slide 18

Slide 18 text

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)

Slide 19

Slide 19 text

NSAttributedString.Key .backgroundColor - എܠ৭ 19 By Taichiro Yoshida (@dataich)

Slide 20

Slide 20 text

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)

Slide 21

Slide 21 text

NSAttributedString.Key .font - ϑΥϯτ 21 By Taichiro Yoshida (@dataich)

Slide 22

Slide 22 text

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)

Slide 23

Slide 23 text

ͦͷଞ • NSAttributedString.Key.paragraphStyle • NSAttributedString.Key.underlineStyle • NSAttributedString.Key.shadow NSAttributedString.Key - NSAttributedString | Apple Developer Documentation 23 By Taichiro Yoshida (@dataich)

Slide 24

Slide 24 text

ඪ४Ͱఏڙ͞Ε͍ͯͳ ͍૷০ 24 By Taichiro Yoshida (@dataich)

Slide 25

Slide 25 text

ྫ: ΠϯϥΠϯίʔυ • എܠΛؙ֯ʹ͍ͨ͠ • എܠʹϘʔμʔΛ෇͚͍ͨ 25 By Taichiro Yoshida (@dataich)

Slide 26

Slide 26 text

ྫ: ίʔυ • จࣈྻ͚ͩ͡Όͳ͘ෳ਺ߦશମͷഎܠΛΧελϜ͍ͨ͠ 26 By Taichiro Yoshida (@dataich)

Slide 27

Slide 27 text

ྫ: Ҿ༻ • ߦ಄ʹॎઢΛҾ͖͍ͨ 27 By Taichiro Yoshida (@dataich)

Slide 28

Slide 28 text

࣮૷ྫ 28 By Taichiro Yoshida (@dataich)

Slide 29

Slide 29 text

ΠϯϥΠϯίʔυ 29 By Taichiro Yoshida (@dataich)

Slide 30

Slide 30 text

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)

Slide 31

Slide 31 text

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)

Slide 32

Slide 32 text

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)

Slide 33

Slide 33 text

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)

Slide 34

Slide 34 text

5. ΧελϜଐੑΛ࣋ͭจࣈྻͷάϦϑ͕දࣔ͞ΕΔCGRectΛऔಘ ͯ͠ඳըॲཧΛߦ͏ • enumerateEnclosingRectsΛ࢖͏ 34 By Taichiro Yoshida (@dataich)

Slide 35

Slide 35 text

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)

Slide 36

Slide 36 text

ίʔυ • جຊతʹ͸ΠϯϥΠϯίʔυͱಉ͡ 36 By Taichiro Yoshida (@dataich)

Slide 37

Slide 37 text

• enumerateEnclosingRectsͰ͸ͳ͘enumerateLineFragments Λ࢖͏ 37 By Taichiro Yoshida (@dataich)

Slide 38

Slide 38 text

enumerateLineFragmentsͰߦྖҬͷCGRectΛऔಘ self.enumerateLineFragments( forGlyphRange: glyphRange) { (rect, usedRect, textContainer, glyphRange, stop) in // άϦϑ͕ඳը͞Ε͍ͯΔߦͷCGRect͕औಘͰ͖ΔͷͰ // ෳ਺ߦͷߴ͞Λܭࢉ͢ΔͳͲ͢Δ } • enumerateEnclosingRects͸άϦϑ͕දࣔ͞Ε͍ͯΔ֤ྖҬͷCGRectΛྻ ڍ • enumerateLineFragments͸άϦϑ͕දࣔ͞Ε͍ͯΔߦྖҬͷCGRectΛྻڍ • boundingRect͸શͯͷάϦϑ͕ऩ·ΔྖҬͷCGRect1ͭ 38 By Taichiro Yoshida (@dataich)

Slide 39

Slide 39 text

boundingRect 39 By Taichiro Yoshida (@dataich)

Slide 40

Slide 40 text

Ҿ༻ • ίʔυͱ΄΅ಉ͡ͰඳըͷίʔυΛม͑ΔͷΈ 40 By Taichiro Yoshida (@dataich)

Slide 41

Slide 41 text

ͦͷଞ • എܠҎ֎ͷ৔߹΋ΦʔόϥΠυ͢΂͖ϝιου͕͋ΔΈ͍ͨ ʢࢼͯ͠ͳ͍ʣ • drawGlyphs • drawStrikethrough • drawUnderline 41 By Taichiro Yoshida (@dataich)

Slide 42

Slide 42 text

·ͱΊ • NSAttributedStringʹΧελϜଐੑΛ௥Ճ͢Δ • NSLayoutManagerΛܧঝͨ͠ΫϥεΛ࡞Δ • CustomLayoutManagerͰඞཁͳඳըϝιουΛΦʔόʔϥΠυ͢Δ • ΧελϜଐੑΛ࣋ͭจࣈྻͷൣғΛ୳͢ • ΧελϜଐੑΛ࣋ͭจࣈྻͷάϦϑ͕දࣔ͞ΕΔCGRectΛऔಘͯ͠ඳ ըॲཧΛߦ͏ • TextKitཧղ͢Δͱָ͍͠ʂ 42 By Taichiro Yoshida (@dataich)

Slide 43

Slide 43 text

ࢀߟ • TextKitΛϚελʔ͠ɺࢥ͍௨ΓʹจࣈΛϨΠΞ΢τ͢Δ • TextKitʹΑΔςΩετϨΠΞ΢τ 43 By Taichiro Yoshida (@dataich)

Slide 44

Slide 44 text

͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ 44 By Taichiro Yoshida (@dataich)