Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ITT 2014 - Max Seelemann - Hello TextKit!

ITT 2014 - Max Seelemann - Hello TextKit!

Max presents TextKit - probably the most significant recent addition to UIKit. iOS 7’s new interface replaces icons and bezels with text, all of which is now driven by the new framework. Max will cover how TextKit came to be, what it’s all about, and, by means of a couple of examples, how things that took weeks before can now be solved in a few lines of code.

Istanbul Tech Talks

May 12, 2014
Tweet

More Decks by Istanbul Tech Talks

Other Decks in Programming

Transcript

  1. 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
  2. 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
  3. Class Cluster TKETextStorage NSTextStorage Abstract - string! - attributesAtIndex:effectiveRange:! !

    - replaceCharactersInRange:withString:! - setAttributes:range: NSAttributedString storage
  4. 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; }
  5. 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];
  6. Code Text Storage TKETextStorage - string! - attributesAtIndex:effectiveRange:! ! -

    replaceCharactersInRange:withString:! - setAttributes:range: Text / Code Attributes TKECodeString storage NSAttributedString cache
  7. 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]; }
  8. 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
  9. 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
  10. 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; }
  11. 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
  12. 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) Test in Istanbul
  13. 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) Test in Istanbul Shorten Line Offset Line
  14. 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]; }
  15. 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 ...
  16. • Indented Line Wrap • Dynamic Line Height • Dynamic

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