hi performance table views with quartzcore and coretext
DESCRIPTION
QuartzCore and CoreText can be used to render text and graphics faster than UIKit elements. In this presentation you will learn some of these tricksTRANSCRIPT
Hi-Performance Table Views with QuartzCore
and CoreText
Mugunth Kumar
Beginners guide to an advanced concept
Steinlogic Consulting and Training Pte Ltd
About me
About me
• Author of the iOS 5, iOS 6 Programming: Pushing the Limits book - Reached the top 100 books in Amazon’s Computer and Technology books list
• Trainer - Conducts training on iOS programming at iOSTraining.sg.
• Developer
• MKNetworkKit (1200+ watchers)
• MKStoreKit (700+ watchers)
• Several other “minor” projects with 200+ watchers
• Clients include startups in Singapore like Squiryl, Found and MNC’s including Microsoft Redmond, Oracle and such.
Why?
• What makes apps pleasant to use?
• Fast scrolling
• Why?
Why?
Why?
• iPhone is a direct manipulation device
Why?
• iPhone is a direct manipulation device
• iPhone screen is closer to your eye than your HDTV or your computer monitor
Why?
• iPhone is a direct manipulation device
• iPhone screen is closer to your eye than your HDTV or your computer monitor
• 60 frames per second = 16.66ms per frame
Why?
• iPhone is a direct manipulation device
• iPhone screen is closer to your eye than your HDTV or your computer monitor
• 60 frames per second = 16.66ms per frame
• Anything less, you will get a headache
Agenda
Agenda
• Why?
Agenda
• Why?
• Three different methods
Agenda
• Why?
• Three different methods
• Pros and Cons
Agenda
• Why?
• Three different methods
• Pros and Cons
• QuartzCore/CoreText introduction
Agenda
• Why?
• Three different methods
• Pros and Cons
• QuartzCore/CoreText introduction
• A simple table view cell example
Agenda
• Why?
• Three different methods
• Pros and Cons
• QuartzCore/CoreText introduction
• A simple table view cell example
• What else can you build? - Facebook style news feed
Compositing Table View Cells
• UITableViewCell
• Subviews (UILabel, UIImageView)
Pros/Cons
Pros/Cons
• Advantages
• Programmatically easy
• Fast for compositing images
• Built in cells are rendered differently
Pros/Cons
• Advantages
• Programmatically easy
• Fast for compositing images
• Built in cells are rendered differently
• Drawbacks
• Slow for text based tables
Direct Drawing
• UITableViewCell drawRect
• NSString -drawInRect, drawAtPoint
• UIImage -drawInRect, drawAtPoint
Pros/Cons
Pros/Cons
• Advantages
• Fast
• Really fast!
Pros/Cons
• Advantages
• Fast
• Really fast!
• Drawbacks
• Difficult (Annoyingly complex to build complex layouts)
• CGContextDrawImage is really slow compared to using UIImageView
Hybrid
• A mix of drawRect + UIImageViews
Cons
Cons
• Still cannot render shadows around images views
Cons
• Still cannot render shadows around images views
self.view.layer.masksToBounds = NO; self.view.layer.shadowColor = [UIColor blackColor].CGColor; self.view.layer.shadowOffset = CGSizeMake(0.0f, -1.0f); self.view.layer.shadowOpacity = 0.5f; self.view.layer.shadowRadius = 1.0f;
Cons
• Still cannot render shadows around images views
self.view.layer.masksToBounds = NO; self.view.layer.shadowColor = [UIColor blackColor].CGColor; self.view.layer.shadowOffset = CGSizeMake(0.0f, -1.0f); self.view.layer.shadowOpacity = 0.5f; self.view.layer.shadowRadius = 1.0f;
• The above code is dog slow.
• Good for views, very bad for table view cells or collection view cells
Is there a better way?
• QuartzCore.framework
• CoreText.framework
Pros/Cons
Pros/Cons
• Advantages
• Fast
• Can render text and image within our 16ms deadline
• Rendering highly customized text is hard
Pros/Cons
• Advantages
• Fast
• Can render text and image within our 16ms deadline
• Rendering highly customized text is hard
This is BOLD and this is in italics.
QuartzCore
• CALayer
• CATextLayer
• CAGradientLayer
• CAShapeLayer
CoreText
• NSAttributedString
• NSMutableAttributedString
• UIBezierPath
Composition
@interface SCTCoreTextCell
@property (strong, nonatomic) CATextLayer *nameTextLayer;@property (strong, nonatomic) CATextLayer *timeTextLayer;@property (strong, nonatomic) CALayer *avatarImageLayer;@property (strong, nonatomic) CALayer *avatarImageShadowLayer;@property (strong, nonatomic) CATextLayer *descriptionTextLayer;
@end
CALayer - Images
self.backgroundLayer = [CALayer layer]; self.backgroundLayer.frame = CGRectMake(0, 0, 320, 150); self.backgroundLayer.contentsScale = [[UIScreen mainScreen] scale]; self.backgroundLayer.actions = [NSDictionary actionsDictionary]; self.backgroundLayer.contents = (id) backgroundImage.CGImage;
self.backgroundLayer.contentsCenter = CGRectMake(1.0/backgroundImage.size.width, 8.0/backgroundImage.size.height, 1.0/backgroundImage.size.width,1.0/backgroundImage.size.height); self.backgroundLayer.contentsGravity = kCAGravityResize;
[self.contentView.layer addSublayer:self.backgroundLayer];
CATextLayer - Text
self.nameTextLayer = [CATextLayer layer]; self.nameTextLayer.frame = CGRectMake(65, 3, 240, 21); self.nameTextLayer.alignmentMode = kCAAlignmentLeft; self.nameTextLayer.wrapped = YES; self.nameTextLayer.contentsScale = [[UIScreen mainScreen] scale]; self.nameTextLayer.actions = [NSDictionary actionsDictionary]; [self.contentView.layer addSublayer:self.nameTextLayer];
Composition
+(NSDictionary*) actionsDictionary { return @{ @"onOrderIn" : [NSNull null], @"onOrderOut" : [NSNull null], @"sublayers" : [NSNull null], @"contents" : [NSNull null], @"position" : [NSNull null], @"bounds" : [NSNull null], @"onLayout" : [NSNull null], @"hidden" : [NSNull null], }; });}
Contents
Contents
• CALayer
• Mostly Images
• Rendering a graphics context in background
Contents
• CALayer
• Mostly Images
• Rendering a graphics context in background
Contents
• CALayer
• Mostly Images
• Rendering a graphics context in background
• CAGradientLayer
• Adding gradient backgrounds
Contents
Contents
• CAShapeLayer
• Mostly Paths
• Use UIBezierPath to create a path
Contents
• CAShapeLayer
• Mostly Paths
• Use UIBezierPath to create a path
Contents
• CAShapeLayer
• Mostly Paths
• Use UIBezierPath to create a path
• CATextLayer (Most useful + complicated)
• Text (NSAttributedString)
NSAttributedString
• The basic building block for complex text rendering
• NSAttributedString = NSString + Attributes Dictionary
Demo 1 - Simple Bold
Composition-(void) setText { CTFontRef ctBoldFont = CTFontCreateWithName((__bridge CFStringRef)[UIFont boldSystemFontOfSize:17].fontName, [UIFont boldSystemFontOfSize:17].pointSize, NULL); NSDictionary *boldAttributes = [NSDictionary dictionaryWithObjectsAndKeys: (__bridge id)ctBoldFont, (id)kCTFontAttributeName, [UIColor blackColor].CGColor, (id)kCTForegroundColorAttributeName, nil]; CFRelease(ctBoldFont);
CTFontRef ctNormalFont = CTFontCreateWithName((__bridge CFStringRef)[UIFont systemFontOfSize:16].fontName, [UIFont systemFontOfSize:16].pointSize, NULL); NSDictionary *normalAttributes = [NSDictionary dictionaryWithObjectsAndKeys: (__bridge id)ctNormalFont, (id)kCTFontAttributeName, [UIColor blackColor].CGColor, (id)kCTForegroundColorAttributeName, nil]; CFRelease(ctNormalFont);
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"iOS Dev Scout is a AWESOME iOS group!" attributes:normalAttributes]; [string addAttributes:boldAttributes range:NSMakeRange(19, 7)]; self.textLayer.string = string;}
Composition
CTFontRef ctNormalFont = CTFontCreateWithName((__bridge CFStringRef)[UIFont systemFontOfSize:16].fontName, [UIFont systemFontOfSize:16].pointSize, NULL); NSDictionary *normalAttributes = [NSDictionary dictionaryWithObjectsAndKeys: (__bridge id)ctNormalFont, (id)kCTFontAttributeName, [UIColor blackColor].CGColor, (id)kCTForegroundColorAttributeName, nil]; CFRelease(ctNormalFont);
Composition
CTFontRef ctBoldFont = CTFontCreateWithName((__bridge CFStringRef)[UIFont boldSystemFontOfSize:17].fontName, [UIFont boldSystemFontOfSize:17].pointSize, NULL); NSDictionary *boldAttributes = [NSDictionary dictionaryWithObjectsAndKeys: (__bridge id)ctBoldFont, (id)kCTFontAttributeName, [UIColor blackColor].CGColor, (id)kCTForegroundColorAttributeName, nil]; CFRelease(ctBoldFont);
Composition
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"iOS Dev Scout is a AWESOME iOS group!" attributes:normalAttributes]; [string addAttributes:boldAttributes range:NSMakeRange(19, 7)]; self.textLayer.string = string;
What did we use?
• kCTForegroundColorAttributeName
• kCTFontAttributeName
What else available?
• kCTCharacterShapeAttributeName
• kCTKernAttributeName
• kCTLigatureAttributeName
• kCTParagraphStyleAttributeName
• kCTStrokeWidthAttributeName
• kCTStrokeColorAttributeName
What else available?
• kCTSuperscriptAttributeName
• kCTUnderlineColorAttributeName
• kCTUnderlineStyleAttributeName
• kCTVerticalFormsAttributeName
• kCTGlyphInfoAttributeName
• kCTRunDelegateAttributeName
• NSLinkAttributeName (only on Mac)
What else available?
• And that is just text.
• Lot more for image rendering
• Even lot more for animation
• NSLinkAttributeName not available on iOS. You should look at OHAttributedLabel or play around with UIButtons
Demo 2 - Facebook
Performance tips
Performance tips
• Use dispatch_once for almost any “constants”
• UIFont, UIBezierPath, UIColor etc.,
Performance tips
• Use dispatch_once for almost any “constants”
• UIFont, UIBezierPath, UIColor etc.,
Performance tips
• Use dispatch_once for almost any “constants”
• UIFont, UIBezierPath, UIColor etc.,
• Use strptime* methods instead of NSDateFormatter
• No support for locale, but crazy fast
Thanks@mugunthkumar
iostraining.sg
Available for consulting services
iOS App Development API DesignMobile UX