Skip to content

Instantly share code, notes, and snippets.

Avatar

Ben Dalziel bdalziel

View GitHub Profile
View GridUtil.m
+ (CGFloat)getUITextElementAboveBaselineHeight:(ASPUITextElement)element traitCollection:(UITraitCollection *)contextTraitCollection {
ASPUITextStyle elementTextStyle = [self mapUIElementToStyle:element elementVariation:ASPUITextElementVariationDefault];
UIFont *font = [ASPFontUtil getUIFont:elementTextStyle traitCollection:contextTraitCollection];
CGFloat lineHeightMultiple = [self getUILineHeightMultiple:elementTextStyle font:font traitCollection:contextTraitCollection];
CGFloat lineHeightAdjustment = 0.0;
if (lineHeightMultiple != 1) {
lineHeightAdjustment = (font.lineHeight - (font.lineHeight * lineHeightMultiple))/2;
}
View ContentTableViewCell.m
// Between Title and Description
// 1. Get height below title baseline which is poking out below a grid line - get the value that would make this poke a whole 8 px.
CGFloat titleDescenderRoundedToNextGridline = 8 - fmod([ASPFontUtil getUITextElementBelowBaselineHeight:ASPUITextElementContentCardTitle traitCollection:contextTraitCollection], 8) ;
// 2. Get height above description baseline that is poking above a grid line - get the value that would make this poke a whole 8 px.
CGFloat descriptionAscenderRoundedToNextGridline = 8 - fmod([ASPFontUtil getUITextElementAboveBaselineHeight:ASPUITextElementContentCardDescription traitCollection:contextTraitCollection], 8) ;
// 3. Round sum of nudges (top and bottom), and make sure we're not putting more than a single grid spacing between them
CGFloat belowTitleMargin = [ASPUtil roundToSubPixelPrecision:titleDescenderRoundedToNextGridline + descriptionAscenderRoundedToNextGridline deviceScale:deviceScale];
if (belowTitleMargin > 8.
View GridUtils.m
+ (CGFloat)getUITextElementBelowBaselineHeight:(ASPUITextElement)element traitCollection:(UITraitCollection *)contextTraitCollection {
// 1. Get the style guide typography style we're using for this UI element
ASPUITextStyle elementTextStyle = [self mapUIElementToStyle:element elementVariation:ASPUITextElementVariationDefault];
UIFont *font = [ASPFontUtil getUIFont:elementTextStyle traitCollection:contextTraitCollection];
// 2. Get line height multiple for typography - this is important because line height affects descender and ascender calculations
CGFloat lineHeightMultiple = [self getUILineHeightMultiple:elementTextStyle font:font traitCollection:contextTraitCollection];
// 3. If we're using a non-default line height, calculate an adjusment
CGFloat lineHeightAdjustment = 0.0;
View ContentTableViewCell.m
// 1. We're trying to align the baseline of the description label with a gridline this far from the bottom of the Content Card
CGFloat targetBottomMargin = smallMargin;
// 2. We need to know how far to nudge the label down. This is a calculation dependent on the UI traits, and is specific to the typography we're using for the description label
CGFloat descriptionLabelBaselineAdjustmentHeight = [ASPFontUtil getUITextElementBelowBaselineHeight:ASPUITextElementContentCardDescription traitCollection:contextTraitCollection];
// 3. Font measurements aren't nice round numbers. I have a utility to round floats to numbers the UI can resonable render at (sub pixel), which is dependent on device scale
CGFloat bottomMargin = [ASPUtil roundToSubPixelPrecision:(targetBottomMargin - descriptionLabelBaselineAdjustmentHeight) deviceScale:deviceScale];
// 4. Use our dynamically adjusted bottom margin and hope it works
self.contentCard.layoutMargins = UIEdgeInsetsMake(smallMargin, gutterWidth, bo
View ContentTableViewCell.m
- (void)handleMargins:(UITraitCollection *)contextTraitCollection {
// 1. Get hold of a bunch of sizes based on the traits of the context we're rendering in
CGFloat deviceScale = [UIScreen mainScreen].scale;
CGFloat smallMargin = [ASPSpacingUtil getSpacing:ASPSpacingSizeSmall traitCollection:contextTraitCollection];
CGFloat gutterWidth = [ASPSpacingUtil getGutterWidth:contextTraitCollection];
CGFloat horizontalMargin = [ASPSpacingUtil getLeftAndRightCellMargins:contextTraitCollection];
// 2. Setup containing margins
// Zero out cell margins, and set horizontal indent on contentview - important for the transition from full bleed to gutters (regular class sizes such as iPad portrait)
View ASPFantasyHomeDataWrangler.m
-(void)wrangleData {
NSMutableArray *wrangledData = [[NSMutableArray alloc] init];
// Read model data into blocks and into wrangledData
// Communicate service state
switch (self.teamService.serviceState) {
case ASPServiceStatePreLoad :
View ASPTableCellUtil.m
+ (void)registerLoadingLifecycleCellNibsForReuseIdentifiers:(UITableView *)tableView
{
[tableView registerNib:[UINib nibWithNibName:@"LoadingCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:ASPTableCellUtilLoadingCellName];
[tableView registerNib:[UINib nibWithNibName:@"LoadErrorCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:ASPTableCellUtilLoadErrorCellName];
[tableView registerNib:[UINib nibWithNibName:@"NoDataCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:ASPTableCellUtilNoDataCellName];
[tableView registerNib:[UINib nibWithNibName:@"PlaceholderCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:ASPTableCellUtilPlaceholderCellName];
}
View FantasyHomeViewController.m
@interface ASPFantasyHomeViewController ()
@property (nonatomic, strong) ASPFantasyHomeDataWrangler *dataWrangler;
@end
@implementation ASPFantasyHomeViewController
View ASPWrangledDataBlockTypes.h
typedef NS_ENUM(NSUInteger, ASPWrangledDataBlockType)
{
ASPWrangledDataBlockTypeLoading,
ASPWrangledDataBlockTypeLoadError,
ASPWrangledDataBlockTypeNoData,
ASPWrangledDataBlockTypePlaceholder,
ASPWrangledDataBlockTypeCustom,
};
View ASPFantasyAthleteHeatStatsTableViewCell.m
// https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITraitEnvironment_Ref/#//apple_ref/occ/intfm/UITraitEnvironment/traitCollectionDidChange:
-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];
[self handleMargins:self.traitCollection];
}
- (void)renderHeatIntoCell:(ASPFantasyPickemGame *)fantasyGame athleteId:(NSString *)athleteId eventId:(NSString *)eventId roundNumber:(NSString *)roundNumber rosterSlot:(NSString *)rosterSlot traitCollection:(UITraitCollection *)contextTraitCollection