Saturday, July 6, 2013

A Simple Server in C++

Makefile


default:
 g++ server.cpp
 ./a.out
clean:
 rm -f a.out

server.cpp


//
//  server.cpp
//  SimpleServer
//
//  Created by Kurry Tran on 7/3/13.
//  Copyright (c) 2013 Kurry Tran. All rights reserved.
//

#include <iostream>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <netdb.h>

void* SocketHandler(void*);

int main(int argc, const char * argv[])
{
    int host_port= 1101;
 struct sockaddr_in my_addr;
 int hsock;
 int *p_int;
    
 socklen_t addr_size = 0;
 int* csock;
 sockaddr_in sadr;
 pthread_t thread_id=0;
    
 hsock = socket(AF_INET, SOCK_STREAM, 0);
 if(hsock == -1){
        std::cout <<"Error initializing socket " << errno << std::endl;
  goto FINISH;
 }
 p_int = (int*)malloc(sizeof(int));
 *p_int = 1;
    
 if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
       (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
        std::cout <<"Error setting options " << errno << std::endl;
  free(p_int);
  goto FINISH;
 }
 free(p_int);
    
 my_addr.sin_family = AF_INET ;
 my_addr.sin_port = htons(host_port);
 
 memset(&(my_addr.sin_zero), 0, 8);
 my_addr.sin_addr.s_addr = INADDR_ANY ;
 
 if( bind( hsock, (sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
        std::cerr << "Error binding to socket, make sure nothing else is listening on this port " << errno << std::endl;
  goto FINISH;
 }
    
 if(listen( hsock, 10) == -1 ){
        std::cerr << "Error listening " << errno << std::endl;
  goto FINISH;
 }
    
 addr_size = sizeof(sockaddr_in);
 
 while(true){
        std::cout <<"waiting for a connection on localhost:"<<host_port<< std::endl;
  csock = (int*)malloc(sizeof(int));
  if((*csock = accept( hsock, (sockaddr*)&sadr, &addr_size))!= -1){
            std::cout <<"---------------------\nReceived connection from "<< inet_ntoa(sadr.sin_addr) << std::endl;
   pthread_create(&thread_id,0,&SocketHandler, (void*)csock );
   pthread_detach(thread_id);
  }
  else{
            std::cerr << "Error accepting " << errno << std::endl;
  }
 }
    
FINISH:
    ;
}

void *SocketHandler(void *lp){
    int *csock = (int *)lp;
    
 char buffer[1024];
 int buffer_len = 1024;
 ssize_t bytecount;
    
 memset(buffer, 0, buffer_len);
 if((bytecount = recv(*csock, buffer, buffer_len, 0))== -1){
        std::cerr << "Error receiving data " << errno << std::endl;
  goto FINISH;
 }
    std::cout << "Received bytes " << bytecount << std::endl << "Received string "<< buffer << std::endl;

 if((bytecount = send(*csock, buffer, strlen(buffer), 0))== -1){
        std::cerr << "Error sending data " << errno << std::endl;
  goto FINISH;
 } 
    std::cout << "Sent bytes " << bytecount << std::endl;
    
FINISH:
    close(*csock);
 free(csock);
    return 0;
}


Wednesday, June 26, 2013

How To Make Fast Scrolling UITableViews With Custom Section Headers and Custom UITableViewCells




1. Create a new master detail application in XCode.

2. To set a custom flat navigation bar color create a two new objective-c categories with the code below and configure the navigation bar by importing the UINavigationBar+FlatUI.h file into your master view controller and calling configureFlatNavigationBarWithColor: on your navigation bar in the viewDidLoad method. You should end up with something like below.




// At the Top of the file
#import "UINavigationBar+FlatUI.h" 

- (void)viewDidLoad
{
    [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a nib.
  self.navigationItem.leftBarButtonItem = self.editButtonItem;
  [self.navigationController.navigationBar configureFlatNavigationBarWithColor:[UIColor colorWithRed:44.0f/255.0f green:71.0f/255.0f blue:98.0f/255.0f alpha:1.0f]];
  UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
  self.navigationItem.rightBarButtonItem = addButton;
}

UINavigationBar+FlatUI.h


//
//  UINavigationBar+FlatUI.h
//  FlatUI
//
//  Created by Jack Flintermann on 5/3/13.
//  Copyright (c) 2013 Jack Flintermann. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UINavigationBar (FlatUI)

- (void) configureFlatNavigationBarWithColor:(UIColor *)color; UI_APPEARANCE_SELECTOR

@end

UINavigationBar+FlatUI.m


//
//  UINavigationBar+FlatUI.m
//  FlatUI
//
//  Created by Jack Flintermann on 5/3/13.
//  Copyright (c) 2013 Jack Flintermann. All rights reserved.
//

#import "UINavigationBar+FlatUI.h"
#import "UIImage+FlatUI.h"

@implementation UINavigationBar (FlatUI)

- (void) configureFlatNavigationBarWithColor:(UIColor *)color {
    [self setBackgroundImage:[UIImage imageWithColor:color cornerRadius:0]
               forBarMetrics:UIBarMetricsDefault & UIBarMetricsLandscapePhone];
    NSMutableDictionary *titleTextAttributes = [[self titleTextAttributes] mutableCopy];
    if (!titleTextAttributes) {
        titleTextAttributes = [NSMutableDictionary dictionary];
    }
    [titleTextAttributes setValue:[UIColor clearColor] forKey:UITextAttributeTextShadowColor];
    [titleTextAttributes setValue:[NSValue valueWithUIOffset:UIOffsetMake(0, 0)] forKey:UITextAttributeTextShadowOffset];
    [self setTitleTextAttributes:titleTextAttributes];
    if([self respondsToSelector:@selector(setShadowImage:)])
    {
        [self setShadowImage:[UIImage imageWithColor:[UIColor clearColor] cornerRadius:0]];
    }
}

@end

UIImage+Color.h


//
//  UIImage+Color.h
//  FlatUI
//
//  Created by Jack Flintermann on 5/3/13.
//  Copyright (c) 2013 Jack Flintermann. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UIImage (FlatUI)

+ (UIImage *)imageWithColor:(UIColor *)color
               cornerRadius:(CGFloat)cornerRadius;

+ (UIImage *) backButtonImageWithColor:(UIColor *)color
                            barMetrics:(UIBarMetrics) metrics
                          cornerRadius:(CGFloat)cornerRadius;

UIImage+Color.m


+ (UIImage *)imageWithColor:(UIColor *)color
               cornerRadius:(CGFloat)cornerRadius {
    CGFloat minEdgeSize = edgeSizeFromCornerRadius(cornerRadius);
    CGRect rect = CGRectMake(0, 0, minEdgeSize, minEdgeSize);
    UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
    roundedRect.lineWidth = 0;
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0f);
    [color setFill];
    [roundedRect fill];
    [roundedRect stroke];
    [roundedRect addClip];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return [image resizableImageWithCapInsets:UIEdgeInsetsMake(cornerRadius, cornerRadius, cornerRadius, cornerRadius)];
}

+ (UIImage *) backButtonImageWithColor:(UIColor *)color
                            barMetrics:(UIBarMetrics) metrics
                          cornerRadius:(CGFloat)cornerRadius {

    CGSize size;
    if (metrics == UIBarMetricsDefault) {
        size = CGSizeMake(50, 30);
    }
    else {
        size = CGSizeMake(60, 23);
    }
    UIBezierPath *path = [self bezierPathForBackButtonInRect:CGRectMake(0, 0, size.width, size.height) cornerRadius:cornerRadius];
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
    [color setFill];
    [path addClip];
    [path fill];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return [image resizableImageWithCapInsets:UIEdgeInsetsMake(cornerRadius, 15, cornerRadius, cornerRadius)];
    
}

3. Now to make the navigation items look flat we can create another objective-c category to change the appearance. Import UIBarButtonItem+FlatUI.h in your master view controller Then add the code below to the viewDidLoad method. You should see something like this:



- (void)viewDidLoad
{
    [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a nib.
  self.navigationItem.leftBarButtonItem = self.editButtonItem;
  [self.navigationController.navigationBar configureFlatNavigationBarWithColor:[UIColor colorWithRed:44.0f/255.0f green:71.0f/255.0f blue:98.0f/255.0f alpha:1.0f]];
  UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
  self.navigationItem.rightBarButtonItem = addButton;
  [UIBarButtonItem configureFlatButtonsWithColor:[UIColor colorWithRed:52.0f/255.0f green:152.0f/255.0f blue:219.0f/255.0f alpha:1.0f]
                                highlightedColor:[UIColor colorWithRed:41.0f/255 green:128.0f/255 blue:185.0f/255 alpha:1.0f]
                                    cornerRadius:3];
}

UIBarButtonItem+FlatUI.h


//
//  UIBarButtonItem+FlatUI.h
//  FlatUI
//
//  Created by Jack Flintermann on 5/8/13.
//  Copyright (c) 2013 Jack Flintermann. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UIBarButtonItem (FlatUI)

// styles a single bar button item
- (void) configureFlatButtonWithColor:(UIColor *)color
                     highlightedColor:(UIColor *)highlightedColor
                         cornerRadius:(CGFloat) cornerRadius UI_APPEARANCE_SELECTOR;

// styles all bar button items that exist within a class heirarchy (same as UIAppearanceProxy methods)
+ (void) configureFlatButtonsWithColor:(UIColor *) color
                      highlightedColor:(UIColor *)highlightedColor
                          cornerRadius:(CGFloat) cornerRadius
                       whenContainedIn:(Class )containerClass, ... NS_REQUIRES_NIL_TERMINATION;

// styles all bar button items (can be overwritten with the above methods)
+ (void) configureFlatButtonsWithColor:(UIColor *) color
                      highlightedColor:(UIColor *)highlightedColor
                          cornerRadius:(CGFloat) cornerRadius;


// removes the text shadows off a single bar button item (sadly, this can't be easily done for all buttons simultaneously)
- (void) removeTitleShadow;

@end

UIBarButtonItem+FlatUI.m


//
//  UIBarButtonItem+FlatUI.m
//  FlatUI
//
//  Created by Jack Flintermann on 5/8/13.
//  Copyright (c) 2013 Jack Flintermann. All rights reserved.
//

#import "UIBarButtonItem+FlatUI.h"
#import "UIImage+FlatUI.h"

@implementation UIBarButtonItem (FlatUI)

- (void) configureFlatButtonWithColor:(UIColor *)color
                     highlightedColor:(UIColor *)highlightedColor
                         cornerRadius:(CGFloat) cornerRadius {
  
  [UIBarButtonItem configureItemOrProxy:self forFlatButtonWithColor:color highlightedColor:highlightedColor cornerRadius:cornerRadius];
  
}

+ (void) configureFlatButtonsWithColor:(UIColor *) color
                      highlightedColor:(UIColor *)highlightedColor
                          cornerRadius:(CGFloat) cornerRadius {
  
  [self configureFlatButtonsWithColor:color highlightedColor:highlightedColor cornerRadius:cornerRadius whenContainedIn:[UINavigationBar class], [UINavigationController class], nil];
}

+ (void) configureFlatButtonsWithColor:(UIColor *) color
                      highlightedColor:(UIColor *)highlightedColor
                          cornerRadius:(CGFloat) cornerRadius
                       whenContainedIn:(Class )containerClass, ... {
  va_list vl;
  va_start(vl, containerClass);
  id appearance = [UIBarButtonItem appearanceWhenContainedIn:containerClass, nil];
  va_end(vl);
  [UIBarButtonItem configureItemOrProxy:appearance forFlatButtonWithColor:color highlightedColor:highlightedColor cornerRadius:cornerRadius];
}

- (void) removeTitleShadow {
  NSMutableDictionary *titleTextAttributes = [[self titleTextAttributesForState:UIControlStateNormal] mutableCopy];
  if (!titleTextAttributes) {
    titleTextAttributes = [NSMutableDictionary dictionary];
  }
  [titleTextAttributes setValue:[NSValue valueWithUIOffset:UIOffsetMake(0, 0)] forKey:UITextAttributeTextShadowOffset];
  [self setTitleTextAttributes:titleTextAttributes forState:UIControlStateNormal];
}

//helper method, basically a wrapper to allow creating a custom UIAppearance method that doesn't conform to the usual naming style
+ (void) configureItemOrProxy:(id)appearance
       forFlatButtonWithColor:(UIColor *)color
             highlightedColor:(UIColor *)highlightedColor
                 cornerRadius:(CGFloat) cornerRadius {
  UIImage *backButtonPortraitImage = [UIImage backButtonImageWithColor:color
                                                            barMetrics:UIBarMetricsDefault
                                                          cornerRadius:cornerRadius];
  UIImage *highlightedBackButtonPortraitImage = [UIImage backButtonImageWithColor:highlightedColor
                                                                       barMetrics:UIBarMetricsDefault
                                                                     cornerRadius:cornerRadius];
  UIImage *backButtonLandscapeImage = [UIImage backButtonImageWithColor:color
                                                             barMetrics:UIBarMetricsLandscapePhone
                                                           cornerRadius:2];
  UIImage *highlightedBackButtonLandscapeImage = [UIImage backButtonImageWithColor:highlightedColor
                                                                        barMetrics:UIBarMetricsLandscapePhone
                                                                      cornerRadius:2];
  
  [appearance setBackButtonBackgroundImage:backButtonPortraitImage
                                  forState:UIControlStateNormal
                                barMetrics:UIBarMetricsDefault];
  [appearance setBackButtonBackgroundImage:backButtonLandscapeImage
                                  forState:UIControlStateNormal
                                barMetrics:UIBarMetricsLandscapePhone];
  [appearance setBackButtonBackgroundImage:highlightedBackButtonPortraitImage
                                  forState:UIControlStateHighlighted
                                barMetrics:UIBarMetricsDefault];
  [appearance setBackButtonBackgroundImage:highlightedBackButtonLandscapeImage
                                  forState:UIControlStateHighlighted
                                barMetrics:UIBarMetricsLandscapePhone];
  
  [appearance setBackButtonTitlePositionAdjustment:UIOffsetMake(1.0f, 1.0f) forBarMetrics:UIBarMetricsDefault];
  [appearance setBackButtonTitlePositionAdjustment:UIOffsetMake(1.0f, 1.0f) forBarMetrics:UIBarMetricsLandscapePhone];
  
  UIImage *buttonImageNormal       = [UIImage imageWithColor:color cornerRadius:cornerRadius];
  UIImage *buttonImageHightlighted = [UIImage imageWithColor:highlightedColor cornerRadius:cornerRadius];
  [appearance setBackgroundImage:buttonImageNormal forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
  [appearance setBackgroundImage:buttonImageHightlighted forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
}

@end
4. To create custom section header views in your tableview create a new section header view class and add a new category and add the code below to your master view controller. Also add the QuartzCore.Framework to your project. You should end up with something like this.








- (void)viewDidLoad
{
    [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a nib.
  self.navigationItem.leftBarButtonItem = self.editButtonItem;
  [self.navigationController.navigationBar configureFlatNavigationBarWithColor:[UIColor colorWithRed:44.0f/255.0f green:71.0f/255.0f blue:98.0f/255.0f alpha:1.0f]];
  UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
  self.navigationItem.rightBarButtonItem = addButton;
  [UIBarButtonItem configureFlatButtonsWithColor:[UIColor colorWithRed:52.0f/255.0f green:152.0f/255.0f blue:219.0f/255.0f alpha:1.0f]
                                highlightedColor:[UIColor colorWithRed:41.0f/255 green:128.0f/255 blue:185.0f/255 alpha:1.0f]
                                    cornerRadius:3];
  // Add This Line
  self.tableView.sectionHeaderHeight = 46.0f;
}

#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{ // Change This to Non Zero Number
  return 100;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{ // Change This to Non Zero Number
  return 1;
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }


//  NSDate *object = _objects[indexPath.row];
  cell.textLabel.text = @"";
    return cell;
}

static NSString *SectionHeaderIdentifier = @"SectionHeaderIdentifier";

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
  SectionHeaderView *headerView = [self.tableView dequeueReusableHeaderFooterViewWithIdentifier:SectionHeaderIdentifier];
  if (headerView == nil) {
    headerView = [[SectionHeaderView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(tableView.frame), tableView.sectionHeaderHeight)];
  }
  [headerView setTitle:@"Title" subTitle:@"Subtitle" image:[UIImage imageNamed:@"search-icon-timeline-translucent@2x.png"]];
  return headerView;
}

UIColor+LightAndDark.h


//
//  UIColor+LightAndDark.h
//  Lua
//
//  Created by Kurry Tran on 12/24/12.
//  Copyright (c) 2012 Lua Technologies. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UIColor (LightAndDark)
- (UIColor *)lighterColor:(CGFloat)percent;
- (UIColor *)darkerColor:(CGFloat)percent;
@end

UIColor+LightAndDark.m


//
//  UIColor+LightAndDark.m
//  Lua
//
//  Created by Kurry Tran on 12/24/12.
//  Copyright (c) 2012 Lua Technologies. All rights reserved.
//

#import "UIColor+LightAndDark.h"

@implementation UIColor (LightAndDark)
//http://stackoverflow.com/questions/11598043/get-slightly-lighter-and-darker-color-from-uicolor

- (UIColor *)lighterColor:(CGFloat)percent
{
  float h, s, b, a;
  if ([self getHue:&h saturation:&s brightness:&b alpha:&a])
    return [UIColor colorWithHue:h
                      saturation:s
                      brightness:MIN(b * (1+percent), 1.0)
                           alpha:a];
  return nil;
}

- (UIColor *)darkerColor:(CGFloat)percent
{
  float h, s, b, a;
  if ([self getHue:&h saturation:&s brightness:&b alpha:&a])
    return [UIColor colorWithHue:h
                      saturation:s
                      brightness:b * (1-percent)
                           alpha:a];
  return nil;
}
@end

SectionHeaderView.h


//
//  SectionHeaderView.h
//  FastScrolling-UITableViews
//
//  Created by Kurry L Tran on 6/26/13.
//  Copyright (c) 2013 Kurry L Tran. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface SectionHeaderView : UIView
{
  NSString *_title;
  NSString *_subTitle;
  UIImage *_image;
}
- (void)setTitle:(NSString *)title subTitle:(NSString *)subTitle;
- (void)setTitle:(NSString *)title subTitle:(NSString *)subTitle image:(UIImage *)image;

SectionHeaderView.m


//
//  SectionHeaderView.m
//  FastScrolling-UITableViews
//
//  Created by Kurry L Tran on 6/26/13.
//  Copyright (c) 2013 Kurry L Tran. All rights reserved.
//

#import "SectionHeaderView.h"
#import "UIColor+LightAndDark.h"
#import <QuartzCore/QuartzCore.h>

@implementation SectionHeaderView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)setTitle:(NSString *)title subTitle:(NSString *)subTitle
{
  _title = title;
  _subTitle = subTitle;
  [self setNeedsDisplay];
}

- (void)setTitle:(NSString *)title subTitle:(NSString *)subTitle image:(UIImage *)image
{
  _title = title;
  _subTitle = subTitle;
  _image = image;
  [self setNeedsDisplay];

}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
  // This Creates a White A Black to White Gradient Layer to Blend With the Solid Color
  CAGradientLayer *gradientLayer = [CAGradientLayer layer];
  [gradientLayer setFrame:rect];
  NSArray *colors = [NSArray arrayWithObjects:
                     (id)[[UIColor whiteColor] CGColor],
                     (id)[[[UIColor blackColor] colorWithAlphaComponent:1.0f] CGColor],
                     nil];
  gradientLayer.colors = colors;
  gradientLayer.opacity = 0.09;
  [self.layer addSublayer:gradientLayer];
  
  // This Generates Three Random Numbers between [0,1] to seed random color
  float r = (float)rand()/(float)RAND_MAX;
  float g = (float)rand()/(float)RAND_MAX;
  float b = (float)rand()/(float)RAND_MAX;

  UIColor *baseColor = [UIColor colorWithRed:r green:g blue:b alpha:1.0f];
  UIColor *topBorderColor = [baseColor lighterColor:0.20];
  UIColor *bottomBorderColor = [baseColor darkerColor:0.20];
  
  // This Draws The Background Color
  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextSetFillColorWithColor(context, baseColor.CGColor);
  CGContextFillRect(context, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height));
  CGContextSaveGState(context);

    // This Draws The Top Border Color
  CGContextMoveToPoint(context, CGRectGetMinX(rect), 0);
  CGContextAddLineToPoint(context, CGRectGetMaxX(rect), 0);
  CGContextSetStrokeColorWithColor(context, topBorderColor.CGColor);
  CGContextSetLineWidth(context, 1);
  CGContextStrokePath(context);
  CGContextRestoreGState(context);
  
  CGContextSaveGState(context);

  // This Draws The Bottom Border Color
  CGContextMoveToPoint(context, CGRectGetMinX(rect), CGRectGetMaxY(rect));
  CGContextAddLineToPoint(context, CGRectGetMaxX(rect), CGRectGetMaxY(rect));
  CGContextSetStrokeColorWithColor(context, bottomBorderColor.CGColor);
  CGContextSetLineWidth(context, 1);
  CGContextStrokePath(context);
  CGContextRestoreGState(context);
  
  CGRect titleLabelFrame = self.bounds;
  titleLabelFrame.origin.x = 69.0;
  titleLabelFrame.origin.y = 8.0;
  
  static UIColor *titleColor;
  titleColor = [UIColor whiteColor];
  static UIColor *subTitleColor;
  subTitleColor = [UIColor whiteColor];
  [titleColor set];
  CGContextSaveGState(context);
  context = UIGraphicsGetCurrentContext();
  CGContextSetBlendMode(context, kCGBlendModeNormal);
  
// Draws Title
  [_title drawAtPoint:CGPointMake(titleLabelFrame.origin.x, titleLabelFrame.origin.y)
            forWidth:200
            withFont:[UIFont boldSystemFontOfSize:17]
            fontSize:17
       lineBreakMode:NSLineBreakByTruncatingTail
  baselineAdjustment:UIBaselineAdjustmentAlignCenters];
  
// Draws SubTitle
  [subTitleColor set];
  [_subTitle drawAtPoint:CGPointMake(69, 25)
               forWidth:200
               withFont:[UIFont systemFontOfSize:13.0]
               fontSize:13
          lineBreakMode:NSLineBreakByTruncatingTail
     baselineAdjustment:UIBaselineAdjustmentAlignCenters];

  [_image drawInRect:CGRectMake(10.0, 10.0, 30.0, 28.0)];
}


@end


5. To custom draw fast tableview cells create a subclass of ABTableViewCell: https://github.com/enormego/ABTableViewCell, which draws the cell with core graphics. You should end up with something like this:
















ABTableViewCell.h


// Copyright (c) 2008 Loren Brichter
// 
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
//  ABTableViewCell.h
//
//  Created by Loren Brichter
//  Copyright 2008 Loren Brichter. All rights reserved.
//

#import <UIKit/UIKit.h>

// to use: subclass ABTableViewCell and implement -drawContentView:
@interface ABTableViewCell : UITableViewCell
{
 UIView *contentView;
}

- (void)drawContentView:(CGRect)r; // subclasses should implement

@end


ABTableViewCell.m


// Copyright (c) 2008 Loren Brichter
// 
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
//  ABTableViewCell.m
//
//  Created by Loren Brichter
//  Copyright 2008 Loren Brichter. All rights reserved.
// 

#import "ABTableViewCell.h"
@interface ABTableViewCellView : UIView
@end

@implementation ABTableViewCellView

- (void)drawRect:(CGRect)r
{
 [(ABTableViewCell *)[self superview] drawContentView:r];
}

@end



@implementation ABTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
 if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
  contentView = [[ABTableViewCellView alloc]initWithFrame:CGRectZero];
  contentView.opaque = YES;
  [self addSubview:contentView];
 }
 return self;
}


- (void)setFrame:(CGRect)f
{
 [super setFrame:f];
 CGRect b = [self bounds];
 //b.size.height -= 1; // leave room for the seperator line
 [contentView setFrame:b];
}

- (void)setNeedsDisplay
{
 [super setNeedsDisplay];
 [contentView setNeedsDisplay];
}

- (void)drawContentView:(CGRect)r
{
 // subclasses should implement this
}

@end


KTTableViewCell.h


//
//  KTTableViewCell.h
//  FastScrolling-UITableViews
//
//  Created by Kurry Tran on 6/27/13.
//  Copyright (c) 2013 Kurry L Tran. All rights reserved.
//

#import "ABTableViewCell.h"

@interface KTTableViewCell : ABTableViewCell
{
    NSString *_title;
    NSString *_subTitle;
    UIImage *_image;
}
- (void)setTitle:(NSString *)title subTitle:(NSString *)subtitle image:(UIImage *)image;
@end




//
//  KTTableViewCell.m
//  FastScrolling-UITableViews
//
//  Created by Kurry Tran on 6/27/13.
//  Copyright (c) 2013 Kurry L Tran. All rights reserved.
//

#import "KTTableViewCell.h"

@implementation KTTableViewCell

- (void)setTitle:(NSString *)title subTitle:(NSString *)subtitle image:(UIImage *)image
{
    _title = title;
    _subTitle = subtitle;
    _image = image;
    [self setNeedsDisplay];
}

-(void) drawContentView:(CGRect)r
{
    static UIColor *textColor;
    textColor = [UIColor blackColor];
    static UIColor *borderColor;
    borderColor = [UIColor colorWithRed:200.0f/255.0f green:200.0f/255.0f blue:200.0f/255.0f alpha:1.0f];
    static UIColor *selectedColor;
    selectedColor = [UIColor colorWithRed:212.0f/255.0f green:212.0f/255.0f blue:212.0f/255.0f alpha:1.0f];
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    if(self.highlighted || self.selected)
 {
        r.origin.y -= 1.0f;
        r.size.height += 1.0f;
        CGContextSetFillColorWithColor(context, selectedColor.CGColor);
  CGContextFillRect(context, CGRectMake(0, 0, CGRectGetWidth(r), CGRectGetMaxY(r)));
        CGContextSaveGState(context);
    }
 else
 {
  CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
  CGContextFillRect(context, CGRectMake(0, 0, r.size.width, r.size.height));
        CGContextSaveGState(context);
        
        CGContextMoveToPoint(context, CGRectGetMinX(r), 0);
        CGContextAddLineToPoint(context, CGRectGetMaxX(r), 0);
        CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
        CGContextSetLineWidth(context, 1);
        CGContextStrokePath(context);
        CGContextRestoreGState(context);
        
        CGContextSaveGState(context);
        
        CGContextMoveToPoint(context, CGRectGetMinX(r), CGRectGetMaxY(r));
        CGContextAddLineToPoint(context, CGRectGetMaxX(r), CGRectGetMaxY(r));
        CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
        CGContextSetLineWidth(context, 1);
        CGContextStrokePath(context);
        CGContextRestoreGState(context);
        [_image drawInRect:CGRectMake(5, 5, 45, 45)];
 }

    [textColor set];
    [_title drawAtPoint:CGPointMake(65.0f, 7.0f)
               forWidth:200
               withFont:[UIFont boldSystemFontOfSize:17]
               fontSize:17
          lineBreakMode:NSLineBreakByTruncatingTail
     baselineAdjustment:UIBaselineAdjustmentAlignCenters];
    
    [_subTitle drawAtPoint:CGPointMake(65.0f, 28.0f)
                  forWidth:200
                  withFont:[UIFont systemFontOfSize:16.0f]
                  fontSize:16
             lineBreakMode:NSLineBreakByTruncatingTail
        baselineAdjustment:UIBaselineAdjustmentAlignCenters];
 
}
@end


// Add This At The Top
#import "KTTableViewCell.h"

- (void)viewDidLoad
{
    [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a nib.
  self.navigationItem.leftBarButtonItem = self.editButtonItem;
  [self.navigationController.navigationBar configureFlatNavigationBarWithColor:[UIColor colorWithRed:44.0f/255.0f green:71.0f/255.0f blue:98.0f/255.0f alpha:1.0f]];
  UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
  self.navigationItem.rightBarButtonItem = addButton;
  [UIBarButtonItem configureFlatButtonsWithColor:[UIColor colorWithRed:52.0f/255.0f green:152.0f/255.0f blue:219.0f/255.0f alpha:1.0f]
                                highlightedColor:[UIColor colorWithRed:41.0f/255 green:128.0f/255 blue:185.0f/255 alpha:1.0f]
                                    cornerRadius:3];
  
  self.tableView.sectionHeaderHeight = 46.0f;
// Add This Line 
    self.tableView.rowHeight = 56.0f;
}

// Change this to your new subclass
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    
    KTTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[KTTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }
    [cell setTitle:@"Title" subTitle:@"Subtitle" image:[UIImage imageNamed:@"placeholder@2x.png"]];

//  NSDate *object = _objects[indexPath.row];
  cell.textLabel.text = @"";
    return cell;
}


Full Source Code Here: http://db.tt/7E2EBbln




Tuesday, June 25, 2013

Compiling Objective-C Command Line in OS X Lion and OS X Mountain Lion

Method two worked on my MacBook Air running OS X Lion, and Method One worked on my MacBook Pro running OS X Mountain Lion.

Makefile


default: method_two

method_one:
 export PATH=$PATH:/System/Library/Frameworks
 clang -fobjc-arc main.m –framework Foundation -o program
 ./program

method_two:
 clang -fobjc-gc /System/Library/Frameworks/Foundation.framework/Foundation  main.m -o program 
 ./program

clean:
 rm -f program

main.m


// Remove the \ character -- Google Blogger is Having Problems
#import <\Foundation/Foundation.h\>

int main(int argc, char *argv[])
{
  @autoreleasepool {
 NSLog(@"Hello World!\n");
  }
  return 0;
}

Monday, June 24, 2013

teehan + lax iOS 7 GUI PSD

Hidden Gems in Cocoa Touch / XCode

1. Open Quickly (Command-Shift-O)
2. View Related Files From Toolbar
3. Use breakpoint actions such as log message or play a sound to avoid recompiling.
4. Use debugDescription.
5. Use Objective-C Subscripting.
NSMutableArray *indexedValues = [NSMutableArray array];
indexedValues[0] = @"One";
NSLog(@"value: %@", indexedValues[0]);
NSMutableDictionary *keyedValues = [NSMutableDictionary dictionary];
keyedValues[@"color"] = [UIColor blueColor];
NSLog(@"value: %@", keyedValues[@"color"]);
6. Private declarations not necessary since Xcode 4.3
7. Synthesize not necessary for @property since Xcode 4.4
8. Reverse arrays quickly inline

 NSArray *numbers = @[ @1, @2, @3 ];
 NSArray *reversed = numbers.reverseObjectEnumerator.allObjects;
9.  Guarantee a mutable object

 NSArray *unknown = self.values; // may be nil
 NSMutableArray *newArray = [NSMutableArray arrayWithArray:unknown];
10. Declare and enumerate different collection types

 id collection = values;
 for (id object in collection) {
... }
11. Remove duplicate values in array without NSSet

[array valueForKeyPath:@"@distinctUnionOfObjects.self"]
12. CAGradientLayer

CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = CGRectMake(150, 250, 500, 500);
UIColor *c1 = [UIColor colorWithRed:0.09 green:0.70 blue:0.98 alpha:1.0];
UIColor *c2 = [UIColor colorWithRed:0.07 green:0.41 blue:0.95 alpha:1.0];
UIColor *c3 = [UIColor colorWithRed:0.81 green:0.46 blue:0.93 alpha:1.0];
gradient.colors = @[(id)c2.CGColor, (id)c3.CGColor, (id)c3.CGColor];
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"colors"];
anim.toValue = @[(id)c1.CGColor, (id)c2.CGColor, (id)c2.CGColor];
anim.duration = 4.0;
anim.autoreverses = YES;
anim.repeatCount = 1e100;
[gradient addAnimation:anim forKey:@"colors"];
[self.view.layer addSublayer:gradient];

13. Core Data Private Queue

NSManagedObjectContext *bgContext;
bgContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:
                                    NSPrivateQueueConcurrencyType];
[context performBlock:^{
    // (add, remove, change objects.)
    saveCompleted = [context save:& saveError];
}];

14. Core Data
Really fast fetches
• Only specific properties

 NSFetchRequest
 fetch.propertiesToFetch = @[@"name", @"phone"];
• Only the raw values

fetch.resultType = NSDictionaryResultType 
• Only the object id

 fetch.resultType = NSManagedObjectIDResultType
• Only the count

 fetch.resultType = NSCountResultType

WWDC 2013 Core Data Performance - Optimization and Debugging

These are the things that I thought were most useful to me:

1. Don't fetch more than you need. Only 10 or so rows are visible so set a batch size on your NSFetchRequests.

Example:


NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Contact"];

request.fetchBatchSize = 20;


2. Optimize your data model. Put binary data in separate entities and use external storage. Duplication isn't always a bad thing, if it speeds up your data query.

3. Prefetch relationships if you know you need them.

4. Consider returning dictionaries instead of managed objects.

Example:


NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Quake"];

[request setResultType:NSDictionaryResultType];

[request setPropertiesToFetch:@[@"magnitude"]];


5. Use SQLite to perform your calculations.

Example:


NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Quake"];
NSExpressionDescription *ed = [[NSExpressionDescription alloc] init];
 ed.name = @"minimum";
 ed.expression = [NSExpression expressionForFunction:@"min:"
            arguments:@[ [NSExpression expressionForKeyPath:@"magnitude"]]];
[request setPropertiesToFetch:@[ ed ]];


6. Use SQLite to group your results automatically.

Example:


NSExpressionDescription *ed = [[NSExpressionDescription alloc] init];
 ed.name = @"count";
 ed.expression = [NSExpression expressionForFunction:@"count:"
arguments:@[ [NSExpression expressionForKeyPath:@"magnitude"]]];
 [request setPropertiesToFetch:@[ @"magnitude", ed ]];
 [request setPropertiesToGroupBy:@[ @"magnitude" ]];
7. Use SQL Logging.

Pass argument flags = {1,2,3} on launch:


-com.apple.CoreData.SQLDebug 1


8. Optimize predicates. Text comparisons are expensive. Put numeric comparisons first.


NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Contact"];
Bad:


request.predicate = [NSPredicate predicateWithFormat:@"firstName == %@ AND age > %i", @"John", 40];
Good:

request.predicate = [NSPredicate predicateWithFormat:@"age > %i && firstName == %@", 40, @"John"];
9. Predicate Costs (Low to High):


Beginswith/Endswith < Equality < Contains < Matches



iOS 5 NSFetchedResultsController Sorting Issues With RestKit

We were having issues with NSManagedObjects not being sorted correctly after modifying managed objects locally and saving, but we didn't know why so I had to do some research. I found this post: http://wbyoung.tumblr.com/post/27851725562/core-data-growing-pains which was helpful, and the code snippet below was what fixed it. The issue in iOS 5 is that the NSFetchedResultsController deadlocks when there are changes in a child context. So with RestKit on that particular view controller we just had to switch from using the mainQueueManagedObjectContext to mainQueueManagedObjectContext.parentContext for iOS 5 and it resolved all of our issues.
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)


  NSManagedObjectContext *newManagedObjectContext;
  if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
    newManagedObjectContext = [RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext;
  } else{
    newManagedObjectContext = [RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext.parentContext;
  }
  NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Entity"];
  NSFetchedResultsController *newFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:newManagedObjectContext sectionNameKeyPath:nil cacheName:nil];