TextKitで行うテキスト装飾パターン/Text decoration pattern with TextKit

3e77f9dbec6a87756d1dbdddab283aee?s=47 Nulab Inc.
October 30, 2019

TextKitで行うテキスト装飾パターン/Text decoration pattern with TextKit

3e77f9dbec6a87756d1dbdddab283aee?s=128

Nulab Inc.

October 30, 2019
Tweet

Transcript

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

    (@dataich)
  2. ϓϩϑΟʔϧ • ٢ాଠҰ࿠ @dataich • Swift/Scala • גࣜձࣾψʔϥϘॴଐ • WebαʔϏε

    TypetalkΛ։ൃɾӡ༻த • ΢ΠΠϨ 2 By Taichiro Yoshida (@dataich)
  3. એ఻ ! 3 By Taichiro Yoshida (@dataich)

  4. Backlog 4 By Taichiro Yoshida (@dataich)

  5. Cacoo 5 By Taichiro Yoshida (@dataich)

  6. Typetalk 6 By Taichiro Yoshida (@dataich)

  7. ࠓ೔͓࿩͢Δ͜ͱ • TextKitͰߦ͏ςΩετ૷০ύλʔϯ • TextKitͱ͸ • ඪ४Ͱఏڙ͞Ε͍ͯΔ૷০ • ຊ୊ •

    ඪ४Ͱఏڙ͞Ε͍ͯͳ͍૷০ • ࣮૷ύλʔϯ • ·ͱΊ 7 By Taichiro Yoshida (@dataich)
  8. ιʔείʔυ dataich/TextKitSample 8 By Taichiro Yoshida (@dataich)

  9. TextKitͱ͸ TextKit | Apple Developer Documentation • ςΩετͷϨΠΞ΢τΛίϯτϩʔϧ͢Δ༷ʑͳΫϥεͷू·Γ • NSAttributedString

    • NSTextStorage (NSMutableAttributedString) • NSLayoutManager • NSTextContainer • UILabelɺUITextViewͳͲΛ࢖͍ͬͯΕ͹ࣗવͱͦͷҰ෦Λ࢖͍ͬͯΔ 9 By Taichiro Yoshida (@dataich)
  10. ग़య - Text Programming Guide for iOS 10 By Taichiro

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

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

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

    • ྫʣ ପԁܗͷςΩετίϯςφ 13 By Taichiro Yoshida (@dataich)
  14. NSLayoutManager • NSTextStorage͕࣋ͭจࣈྻΛϨΠΞ΢τ͠දࣔ͢Δ • NSTextStorageͷมߋ௨஌Λड͚औΓඳը • UnicodeͷจࣈΛάϦϑʹϚοϓ͠ɺͦΕΛNSTextContainerʹ ηοτ • ߋʹͦͷNSTextContainerΛUITextViewͳͲʹηοτ

    • ඳը͞Ε͍ͯΔάϦϑͷ࠲ඪΛ஌͍ͬͯΔ 14 By Taichiro Yoshida (@dataich)
  15. ඪ४Ͱఏڙ͞Ε͍ͯΔ ૷০ 15 By Taichiro Yoshida (@dataich)

  16. ྫ let text = """ ෱ԬͷiOSΤϯδχΞୡ͕ओ࠵͢Δɺ ϓϩάϥϛϯάݴޠ Swift ͱͦͷपลٕज़ͷษڧձͰ͢ɻ ൃలΛଓ͚Δ

    Swift ͱͦͷपลٕज़ͷಈ޲Λ௥͍ɺ ॳ৺ऀ/্ڃऀ/࿝एஉঁΛ໰Θͣɺ৘ใަ׵ͷ৔ͱͯ͠ ػೳ͢Δ͜ͱΛ໨తͱ͍ͯ͠·͢ɻ """ 16 By Taichiro Yoshida (@dataich)
  17. NSAttributedString.Key .foregroundColor - จࣈ৭ 17 By Taichiro Yoshida (@dataich)

  18. 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)
  19. NSAttributedString.Key .backgroundColor - എܠ৭ 19 By Taichiro Yoshida (@dataich)

  20. 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)
  21. NSAttributedString.Key .font - ϑΥϯτ 21 By Taichiro Yoshida (@dataich)

  22. 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)
  23. ͦͷଞ • NSAttributedString.Key.paragraphStyle • NSAttributedString.Key.underlineStyle • NSAttributedString.Key.shadow NSAttributedString.Key - NSAttributedString

    | Apple Developer Documentation 23 By Taichiro Yoshida (@dataich)
  24. ඪ४Ͱఏڙ͞Ε͍ͯͳ ͍૷০ 24 By Taichiro Yoshida (@dataich)

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

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

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

  28. ࣮૷ྫ 28 By Taichiro Yoshida (@dataich)

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

  30. 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)
  31. 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)
  32. 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)
  33. 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)
  34. 5. ΧελϜଐੑΛ࣋ͭจࣈྻͷάϦϑ͕දࣔ͞ΕΔCGRectΛऔಘ ͯ͠ඳըॲཧΛߦ͏ • enumerateEnclosingRectsΛ࢖͏ 34 By Taichiro Yoshida (@dataich)

  35. 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. ίʔυ • جຊతʹ͸ΠϯϥΠϯίʔυͱಉ͡ 36 By Taichiro Yoshida (@dataich)

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

  38. enumerateLineFragmentsͰߦྖҬͷCGRectΛऔಘ self.enumerateLineFragments( forGlyphRange: glyphRange) { (rect, usedRect, textContainer, glyphRange, stop)

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

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

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

    41 By Taichiro Yoshida (@dataich)
  42. ·ͱΊ • NSAttributedStringʹΧελϜଐੑΛ௥Ճ͢Δ • NSLayoutManagerΛܧঝͨ͠ΫϥεΛ࡞Δ • CustomLayoutManagerͰඞཁͳඳըϝιουΛΦʔόʔϥΠυ͢Δ • ΧελϜଐੑΛ࣋ͭจࣈྻͷൣғΛ୳͢ •

    ΧελϜଐੑΛ࣋ͭจࣈྻͷάϦϑ͕දࣔ͞ΕΔCGRectΛऔಘͯ͠ඳ ըॲཧΛߦ͏ • TextKitཧղ͢Δͱָ͍͠ʂ 42 By Taichiro Yoshida (@dataich)
  43. ࢀߟ • TextKitΛϚελʔ͠ɺࢥ͍௨ΓʹจࣈΛϨΠΞ΢τ͢Δ • TextKitʹΑΔςΩετϨΠΞ΢τ 43 By Taichiro Yoshida (@dataich)

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