Pro Yearly is on sale from $80 to $50! »

UIKonf '14: TextKit For The Rest Of Us

UIKonf '14: TextKit For The Rest Of Us

TextKit is Apple's way to layout, render and edit text on iOS 7. This new collection of classes enables developers to work with text in unprecedented ways.

After shedding some light on mysterious class names, this talk will highlight a few of those new possibilities. Things you never dared asking for are now are just a few lines of code away.

9dc42f7d1185b03042f754dd1cf0f805?s=128

Max Seelemann

May 14, 2014
Tweet

Transcript

  1. TextKit! For The Rest Of Us Max Seelemann – The

    Soulmen – @macguru17
  2. ulyssesapp.com

  3. There is no short introduction to TextKit But we’ll do

    one anyway…
  4. None
  5. • Architecture History • Syntax Highlighting • Paragraph Numbers

  6. Architecture History

  7. UITextView NSString Text User Model View Controller iOS 2 iOS

    2
  8. UITextView NSString Text User Model View iOS 2 iOS 2

    UITextInput iOS 3.2 Core Text iOS 3.2 NSAttributedString iOS 3.2
  9. UITextView NSString Text User Model View iOS 2 iOS 2

    UITextInput iOS 3.2 Custom View Custom Layout Core Text iOS 3.2 NSAttributedString iOS 3.2
  10. UITextView NSString Text User Model View iOS 2 iOS 2

    UITextInput iOS 3.2 Core Text iOS 3.2 NSAttributedString iOS 3.2 iOS 4
  11. UITextView NSString Text User Model View iOS 2 iOS 2

    UITextInput iOS 3.2 Core Text iOS 3.2 NSAttributedString iOS 3.2 iOS 5
  12. UITextView Text User Model View iOS 2 UITextInput iOS 3.2

    Core Text iOS 3.2 NSAttributedString iOS 3.2 iOS 6
  13. UITextView NSTextStorage Text User Model View Controller NSLayoutManager iOS 7

    iOS 7 NSTextContainer iOS 7 iOS 2
  14. UITextView NSTextStorage Text User Model View Controller NSLayoutManager iOS 7

    iOS 7 NSTextContainer iOS 7 iOS 2 Store Text Control Layout Define Text Area Display + Input
  15. UITextView NSTextStorage NSLayoutManager NSTextContainer textStorage = [NSTextStorage new]; 1 layoutManager

    = [NSLayoutManager new];! [textStorage addLayoutManager: layoutManager]; 2 textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(…, …)];! [layoutManager addTextContainer: textContainer]; 3 textView = [[UITextView alloc] initWithFrame:… textContainer:textContainer]; 4
  16. Syntax Highlighting

  17. Comments Pragmas Keywords

  18. NSTextStorage Store Text NSTextContainer Define Text Area Model NSLayoutManager Control

    Layout Controller UITextView Display + Input View
  19. NSTextStorage Store Text + Attributes

  20. Class Cluster TKETextStorage NSTextStorage Abstract - string! - attributesAtIndex:effectiveRange:! !

    - replaceCharactersInRange:withString:! - setAttributes:range: NSAttributedString storage
  21. Simple Text Storage TKETextStorage NSAttributedString storage - (NSString *)string {

    return [storage string]; } - (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range { return [storage attributesAtIndex:location effectiveRange:range]; } - (id)init { self = [super init]; ! if (self) { storage = [NSMutableAttributedString new]; } return self; }
  22. Simple Text Storage - (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range { [storage setAttributes:attrs

    range:range]; ! } - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str { [storage replaceCharactersInRange:range withString:str]; ! ! ! } [self edited:NSTextStorageEditedCharacters range:range changeInLength:(NSInteger)str.length - (NSInteger)range.length]; [self edited:NSTextStorageEditedAttributes range:range changeInLength:0];
  23. None
  24. Code Text Storage TKETextStorage - string! - attributesAtIndex:effectiveRange:! ! -

    replaceCharactersInRange:withString:! - setAttributes:range: Text / Code Attributes TKECodeString storage NSAttributedString cache
  25. Code Text Storage - (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range { [cache setAttributes:attrs

    range:range]; ! [self edited:NSTextStorageEditedAttributes range:range changeInLength:0]; } - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str { [storage replaceCharactersInRange:range withString:str]; [cache replaceCharactersInRange:range withString:str]; ! [self edited:NSTextStorageEditedCharacters range:range changeInLength:(NSInteger)str.length - (NSInteger)range.length]; }
  26. Text Storage Mutation -beginEditing -endEditing -replaceCharactersInRange:… Notify Change

  27. Text Storage Mutation -beginEditing -endEditing -processEditing -replaceCharactersInRange:… All textual changes

    done -replaceCharactersInRange:… Compute colors Notify Change
  28. Compute Colors - (void)processEditing { ... // Clean up colors

    ! ! [self.content enumerateCodeInRange:range usingBlock:^(NSRange range, TKECodeType type) { ! [self addAttribute:NSForegroundColorAttributeName value:[self textColorForCodeType: type] range:range]; ! }]; ! [super processEditing]; } CodeString knows code TextStorage maps colors
  29. None
  30. Paragraph Numbers

  31. None
  32. None
  33. NSTextContainer Define Text Area NSTextStorage Store Text Model NSLayoutManager Control

    Layout Controller UITextView Display + Input View
  34. NSTextContainer Define Text Area

  35. NSTextContainer Vivamus et turpis in dui blandit pulvinar nec dignissim

    diam. Nulla scelerisque posuere viverra. Quisque nibh nunc, consequat vel luctus in, consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum enim. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus hendrerit venenatis libero, vitae sodales lacus elementum eget. Duis sit amet risus ac nunc blandit lobortis vel sed nibh. Suspendisse laoreet odio ac ligula aliquam scelerisque. Nulla volutpat consectetur sem tincidunt cursus. In ac justo in libero. Fusce tincidunt erat sit amet magna porttitor nec iaculis diam varius. Aliquam eget odio leo. Sed faucibus, libero non consectetur tristique, metus leo tempus libero, quis ornare felis purus in odio. Proin metus arcu, dictum id faucibus gravida, pulvinar ut metus. Mauris nisl sapien, cursus nec auctor quis, bibendum vitae. Etiam id nisl libero, nec consequat dolor. Fusce id ornare enim. Praesent viverra rutrum erat, eu gravida erat scelerisque at. Donec sed lectus leo. Nunc vel volutpat libero. Maecenas euismod molestie neque non feugiat. Vestibulum hendrerit lorem leo, condimentum imperdiet velit. Quisque urna nisi, faucibus id Vivamus et turpis in dui blandit pulvinar nec dignissim diam. Nulla scelerisque posuere viverra. Quisque nibh nunc, consequat vel luctus in, consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum enim. Cum sociis natoque penatibus et magnis dis p a r t u r i e n t montes, nascetur r i d i c u l u s m u s . P h a s e l l u s hendrerit venenatis libero, v i t a e s o d a l e s l a c u s elementum eget. Duis sit amet risus ac nunc b l a n d i t lobortis vel sed nibh. Suspendisse laoreet o d i o a c ligula aliquam scelerisque. Nulla volutpat consectetur sem tincidunt cursus. In ac justo in libero. Fusce tincidunt erat sit amet magna porttitor nec iaculis diam varius. Aliquam eget odio leo. Sed faucibus, libero non consectetur tristique, metus leo tempus libero, quis ornare felis purus in odio. Proin metus arcu, dictum id faucibus gravida, pulvinar ut metus. Mauris nisl sapien, cursus nec auctor quis, bibendum vitae. Etiam id nisl libero, nec consequat dolor. Fusce id ornare enim. Praesent viverra rutrum erat, eu gravida erat scelerisque at. Donec sed Vivamus et turpis in dui blandit pulvinar nec dignissim diam. Nulla scelerisque posuere viverra. Quisque nibh nunc, c o n s e q u a t v e l l u c t u s i n , consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. S u s p e n d i s s e p o t e n t i . Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum enim. C u m s o c i i s n a t o q u e penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus hendrerit venenatis libero, v i t a e s o d a l e s l a c u s elementum eget. Duis sit amet risus ac nunc blandit l o b o r t i s v e l s e d n i b h . Suspendisse laoreet odio ac ligula aliquam scelerisque. Nulla volutpat consectetur sem tincidunt cursus. In ac justo in libero. Fusce tincidunt erat sit amet magna porttitor nec iaculis diam varius. Aliquam eget odio leo. Sed faucibus, Vivamus et turpis in dui blandit pulvinar nec dignissim diam. Nulla scelerisque posuere viverra. Quisque nibh nunc, consequat vel luctus in, consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum enim. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus hendrerit venenatis libero, vitae sodales lacus elementum eget. Duis sit amet risus ac nunc blandit lobortis vel sed nibh. Suspendisse laoreet odio ac ligula aliquam scelerisque. Nulla volutpat consectetur sem tincidunt cursus. In ac justo in libero. Fusce tincidunt erat sit amet magna porttitor nec iaculis diam varius. Aliquam eget odio leo. Sed faucibus, libero non consectetur tristique, metus leo tempus libero, quis ornare felis purus in odio. Proin metus arcu, dictum id faucibus gravida, pulvinar ut metus. Mauris nisl sapien, cursus nec auctor quis, bibendum vitae. Define Text Area
  36. Line Fragment Rect - (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect

  37. Line Fragment Rect - (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect

  38. Line Fragment Rect - (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect

  39. Line Fragment Rect - (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect

  40. Line Fragment Rect - (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect

  41. Insetting Text Container - (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect {

    CGRect rect = [super lineFragmentRectForProposedRect:proposedRect atIndex:characterIndex writingDirection:baseWritingDirection remainingRect:remainingRect]; ! rect.origin.x += inset; rect.size.width -= inset; ! return rect; } Hangs the text layout
  42. NSTextContainer NSTextStorage NSLayoutManager Control Layout UITextView Define Text Area Store

    Text Display + Input
  43. NSTextContainer NSTextStorage NSLayoutManager Control Layout UITextView

  44. NSTextContainer NSTextStorage NSLayoutManager UITextView NSGlyphGenerator NSTypesetter Create Layout Store Layout

  45. NSTextContainer NSTextStorage NSLayoutManager UITextView NSGlyphGenerator NSTypesetter Create Layout Store Layout

    NSLayoutManager Delegate
  46. NSTextContainer NSTextStorage NSLayoutManager UITextView NSGlyphGenerator NSTypesetter Create Layout Control Layout

    NSLayoutManager Delegate
  47. Typesetting View (UITextContainer) Text (NSTextStorage) (NSTypesetter) Vivamus et turpis in

    dui blandit pulvinar nec dignissim diam. Nulla scelerisque posuere viverra. Quisque nibh nunc, consequat vel luctus in, consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere Line Fragment Rect Characters to Glyphs A → A Text Attributes Store Layout (NSLayoutManager)
  48. Typesetting View (UITextContainer) Text (NSTextStorage) (NSTypesetter) Vivamus et turpis in

    dui blandit pulvinar nec dignissim diam. Nulla scelerisque posuere viverra. Quisque nibh nunc, consequat vel luctus in, consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere Line Fragment Rect Characters to Glyphs A → A Text Attributes Store Layout (NSLayoutManager) UIKonf in Berlin
  49. Typesetting View (UITextContainer) Text (NSTextStorage) (NSTypesetter) Vivamus et turpis in

    dui blandit pulvinar nec dignissim diam. Nulla scelerisque posuere viverra. Quisque nibh nunc, consequat vel luctus in, consectetur vitae mauris. Nunc lacinia malesuada mauris, sed egestas nunc fermentum nec. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere Line Fragment Rect Characters to Glyphs A → A Text Attributes Store Layout (NSLayoutManager) UIKonf in Berlin Shorten Line Offset Line
  50. Offsetting Line Fragment - (void)setLineFragmentRect:(CGRect)fragmentRect forGlyphRange:(NSRange)glyphRange usedRect:(CGRect)usedRect { fragmentRect.origin.x +=

    inset; usedRect.origin.x += inset; [super setLineFragmentRect:fragmentRect forGlyphRange:glyphRange usedRect:usedRect]; }
  51. Paragraph numbers - (void)drawBackgroundForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin { [super drawBackgroundForGlyphRange:glyphsToShow atPoint:origin]; !

    ! ! ! ! ! ! ! ! ! ! ! ! ! ! } // Enumerate all lines NSUInteger glyphIndex = glyphRange.location; while (glyphIndex < NSMaxRange(glyphRange)) { ! ! ! ! ! ! ! ! // Advance glyphIndex = NSMaxRange(glyphLineRange); } NSRange glyphLineRange; CGRect lineRect = [self lineFragmentRectForGlyphAtIndex:glyphIndex effectiveRange:&glyphLineRange]; ! // Drawing ...
  52. Demo

  53. Model View Controller Store Text Control Layout Define Text Area

    Display + Input UITextView NSTextStorage NSLayoutManager NSTextContainer
  54. • Indented Line Wrap • Dynamic Line Height • Dynamic

    Tab Size github.com/macguru/TextKitEditor TextKitEditor on GitHub Max Seelemann – @macguru17