Creating a simple UICollectionView in iOS


1) Create Master-Detail Application & Replace the MasterViewController

First we want to create a Master-Detail Application just because it sets up a Master-Detail relationship even though thats the first thing we are going to break :).  So go ahead and create a new project in XCode4 based on a Master-Detail Application type.  Use ARC, Storyboards and CoreData because we will use CoreData to store information.  Your storyboard should look like this:

Master-Detail Storyboard
Master-Detail Storyboard

Now select the Master scene until its highlighted in blue and delete it with the Delete key.  We simply replace it by dragging in a UICollectionViewController onto the storyboard in its place.  This places a UICollectionViewController scene with a small empty collectionview cell in the top left corner.  I made a few adjustments to mine and here is what it looks like but Ill go over those later:

UICollectionViewController Storyboard
UICollectionViewController Storyboard

The changes I made to it are the following:

a – Select the entire scene (again until its highlighted blue) and change its Class type from UICollectionViewController to MasterViewController.

b – Enlarged the UICollectionViewCell from 50×50 to 145×145 in the Dimension’s Inspector

Here are some clips of the Identity Inspector of the MasterViewController and Dimension’s Inspector of the UICollectionViewCell:

UICollectionViewController Identity Inspector
UICollectionViewController Identity Inspector
UICollectionViewCell Dimensions Inspector
UICollectionViewCell Dimensions Inspector

We did set the new UICollectionViewController to a new class, the MasterViewController class.  We must do the same with the UICollectionViewCell but we must create its class first.

2)  Modify the MasterViewController class with the following in the .m file:

#import “MasterViewController.h”

#import “DetailViewController.h”

#import “MyCustomCell.h”

#import “AppDelegate.h”

static NSString *CellIdentifier = @”MyCustomCell”;

@interface MasterViewController ()


NSMutableArray *_objectChanges;

NSMutableArray *_sectionChanges;



Now let’s go through the methods.  First the UICollectionView methods, which are quite similar to the UITableViewController methods:

#pragma mark – UICollectionView

– (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section


id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];

return [sectionInfo numberOfObjects];


// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:

– (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath


MyCustomCell *cell = (MyCustomCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];

NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];

[cell setImage:[UIImage imageWithData:[object valueForKey:@”photoImageData”]]];

return cell;


– (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender


if ([[segue identifier] isEqualToString:@”showDetail”]) {

NSIndexPath *indexPath = [[self.collectionView indexPathsForSelectedItems] lastObject];

NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];

[[segue destinationViewController] setDetailItem:object];



The MyCustomCell Class is the one we will create in the next section.  For now we are simply filling in the cell’s image data with some fetched managed object which we will also create later.  A couple of more interesting tidbits for example; we gave our UICollectionViewCell a reuse identifier and we gave our segue an identifier as well.  We must make sure these identifiers also exist in the storyboard inspectors for the cell and segue respectively.

3) Create UICollectionViewCell Class & Connect it

Let’s go ahead and Create a New File in our project, base it off of Objective C Class.  Type in UICollectionViewCell as the subclass and name it MyCustomCell.  We are simply going to define a class for our UICollectionViewCell and once we are finished, we must go to Storyboard and set our cell to use this new class type.

Add a UIImageView property to the class so that your .h file looks like this:

#import <UIKit/UIKit.h>

@interface MyCustomCell : UICollectionViewCell{

IBOutlet UIImageView *imageView;


-(void)setImage:(UIImage *)image;


and now implement the setter in your .m so that it looks like this:

#import “MyCustomCell.h”

@implementation MyCustomCell

-(void)setImage:(UIImage *)image{

[imageView setImage:image];



4) Create the data model.  First let’s do the easiest part, which is creating the data model.  Select your project’s xcdatamodel file and create a new Entity, call it Snapshots if you’d like.  Now add 3 attributes to it and make them of this type:

Core Data Entity Data Model
Core Data Entity Data Model

Once that is done, we have a storage container for our data.  Let’s look at the code used by our app to access this store and manipulate it.

#pragma mark – Fetched results controller

– (NSFetchedResultsController *)fetchedResultsController


if (_fetchedResultsController != nil) {

return _fetchedResultsController;


NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

// Edit the entity name as appropriate.

NSEntityDescription *entity = [NSEntityDescription entityForName:@”Snapshots” inManagedObjectContext:self.managedObjectContext];

[fetchRequest setEntity:entity];

// Set the batch size to a suitable number.

[fetchRequest setFetchBatchSize:20];

// Edit the sort key as appropriate.

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@”photoName” ascending:NO];

NSArray *sortDescriptors = @[sortDescriptor];

[fetchRequest setSortDescriptors:sortDescriptors];

// Edit the section name key path and cache name if appropriate.

// nil for section name key path means “no sections”.

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@”Master”];

aFetchedResultsController.delegate = self;

self.fetchedResultsController = aFetchedResultsController;

NSError *error = nil;

if (![self.fetchedResultsController performFetch:&error]) {

// Replace this implementation with code to handle the error appropriately.

// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

NSLog(@”Unresolved error %@, %@”, error, [error userInfo]);



return _fetchedResultsController;


– (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo

atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type


NSMutableDictionary *change = [NSMutableDictionary new];

switch(type) {

case NSFetchedResultsChangeInsert:

change[@(type)] = @(sectionIndex);


case NSFetchedResultsChangeDelete:

change[@(type)] = @(sectionIndex);



[_sectionChanges addObject:change];


– (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject

atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type

newIndexPath:(NSIndexPath *)newIndexPath


NSMutableDictionary *change = [NSMutableDictionary new];



case NSFetchedResultsChangeInsert:

change[@(type)] = newIndexPath;


case NSFetchedResultsChangeDelete:

change[@(type)] = indexPath;


case NSFetchedResultsChangeUpdate:

change[@(type)] = indexPath;


case NSFetchedResultsChangeMove:

change[@(type)] = @[indexPath, newIndexPath];



[_objectChanges addObject:change];


– (void)controllerDidChangeContent:(NSFetchedResultsController *)controller


if ([_sectionChanges count] > 0)


[self.collectionView performBatchUpdates:^{

for (NSDictionary *change in _sectionChanges)


[change enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, id obj, BOOL *stop) {

NSFetchedResultsChangeType type = [key unsignedIntegerValue];

switch (type)


case NSFetchedResultsChangeInsert:

[self.collectionView insertSections:[NSIndexSet indexSetWithIndex:[obj unsignedIntegerValue]]];


case NSFetchedResultsChangeDelete:

[self.collectionView deleteSections:[NSIndexSet indexSetWithIndex:[obj unsignedIntegerValue]]];


case NSFetchedResultsChangeUpdate:

[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:[obj unsignedIntegerValue]]];





} completion:nil];


if ([_objectChanges count] > 0 && [_sectionChanges count] == 0)


[self.collectionView performBatchUpdates:^{

for (NSDictionary *change in _objectChanges)


[change enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, id obj, BOOL *stop) {

NSFetchedResultsChangeType type = [key unsignedIntegerValue];

switch (type)


case NSFetchedResultsChangeInsert:

[self.collectionView insertItemsAtIndexPaths:@[obj]];


case NSFetchedResultsChangeDelete:

[self.collectionView deleteItemsAtIndexPaths:@[obj]];


case NSFetchedResultsChangeUpdate:

[self.collectionView reloadItemsAtIndexPaths:@[obj]];


case NSFetchedResultsChangeMove:

[self.collectionView moveItemAtIndexPath:obj[0] toIndexPath:obj[1]];





} completion:nil];


[_sectionChanges removeAllObjects];

[_objectChanges removeAllObjects];


I know its long, but its pretty simple.  The first method, – (NSFetchedResultsController *)fetchedResultsController, basically opens up the store, fetches all entities by the name “Snapshots” and places them into a special object called NSFetchedResultsController.

The didChangeSection method is called when there is a change within a section.  We only have 1 section in our UICollectionView.

The didChangeObject method is called when a particular object is changed within our UICollectionView.

The controllerDidChangeContent actually manages the changes made.  Basically we update our two arrays, _sectionChanges and _objectChanges with each change in the data in order to keep our UICollectionView current.

5) Connect to Flickr API.  So what constitutes a change in those sections and objects?  There is an acronym that datastore managers use, CRUD, which basically says that everytime you create, read, update or delete you create a transaction.  Thats basically what we want to track (except for the read part :)).  So whenever we download a new photo to our datastore, update a photo or delete one, we trigger changes in objects and thus in sections.

We want to use the Flickr API to get images from the web and populate our collection view.  We are basically going to perform a fetch to Flickr API using our own key or identifier.  You must register for one at

a – Get FlickrAPIKey and add it here to this string constant atop your .m file like so:

NSString *const FlickrAPIKey = @"YOURAPIKEYVALUE";

b – Add the loadFlickrPhotos method to fetch pics from the web.  So add this method:

– (void)loadFlickrPhotos{

// 1. Build your Flickr API request w/Flickr API key in FlickrAPIKey.h

NSString *urlString = [NSString stringWithFormat:@”″, FlickrAPIKey, @”bayern”];

NSURL *url = [NSURL URLWithString:urlString];

// 2. Get URLResponse string & parse JSON to Foundation objects.

NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];

NSError *e = nil;

NSDictionary *results = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]options:NSJSONReadingMutableContainers error:&e];

photos = [[results objectForKey:@”photos”] objectForKey:@”photo”];

for (NSDictionary *photo in photos) {

// 3.a Get title for e/ photo

NSString *title = [photo objectForKey:@”title”];

[photoNames addObject:(title.length > 0 ? title : @”Untitled”)];

// 3.b Construct URL for e/ photo.

NSString *photoURLString = [NSString stringWithFormat:@””, [photo objectForKey:@”farm”], [photo objectForKey:@”server”], [photo objectForKey:@”id”], [photo objectForKey:@”secret”]];

[photoURLs addObject:[NSURL URLWithString:photoURLString]];


// Process into CoreData

[self processCoreData];


It basically looks for Flickr photos of Bayern and stores the results in the photos ivar.  Now we must populate our CoreData db with these data.

c – Populate our CoreData model.  Add the processCoreData method to your MasterViewController.m like so:


AppDelegate *myDelegate = [[UIApplication sharedApplication] delegate];

for (NSDictionary *photoDictionary in photos){

NSManagedObject *photoModel = [NSEntityDescription insertNewObjectForEntityForName:@”AFPhotoModel” inManagedObjectContext:myDelegate.managedObjectContext];

//[photoModel setValue:[photoDictionary valueForKey:@”rating”] forKey:@”photoRating”];

[photoModel setValue:[photoDictionary valueForKey:@”title”] forKey:@”photoName”];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

//Build URL

NSString *photoURLString = [NSString stringWithFormat:@””, [photoDictionary objectForKey:@”farm”], [photoDictionary objectForKey:@”server”], [photoDictionary objectForKey:@”id”], [photoDictionary objectForKey:@”secret”]];

NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:photoURLString]];

dispatch_async(dispatch_get_main_queue(), ^{

[photoModel setValue:imageData forKey:@”photoImageData”];





Voila!  Run your app!

iOS Smarties :)

iOS & Objective C Smarties Code Snippets by Marcio Valenzuela
iOS & Objective C Smarties Code Snippets

Everyone loves Smarties!  And much the same way Smarties Candies make you smarter… today we are talking about Code Snippets that make you….er Smarter!  More than a source of cut/paste Objective C source code, this is meant to be a quick reference.  As such, some of these will be incomplete and I will be filling them up as I go along. 

1)   UIAlertView

UIAlertView *internetAlert = [[UIAlertView alloc] initWithTitle:@”No hay farmacias”

message:@”Favor cambie sus parámetros”



otherButtonTitles:@”Ok”, nil];

[internetAlert show];

2)   NSNotification

//1. Register as observer of notifications in viewDidLoad

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveTestNotification:) name:@”TestNotification” object:nil];

//2. NSNotifCtr CLEANUP in viewDidUnload

[[NSNotificationCenter defaultCenter] removeObserver:self];

//4. Post notif to NSNotif in calling method OTHER CLASS

[[NSNotificationCenter defaultCenter]



//3. Method to prove notif received…

– (void) receiveTestNotification:(NSNotification *) notification


if ([[notification name] isEqualToString:@”TestNotification”])

NSLog (@”Successfully received the test notification!”);


3)   UIActivityIndicator – NSTimer – then completion blocks

//1. Set activity indicator

UIApplication *sharedApplication = [UIApplication sharedApplication];

sharedApplication.networkActivityIndicatorVisible = YES;

//INSERT NSTimer here J

//2. Hide activity indicator

UIApplication *sharedApplication = [UIApplication sharedApplication];

sharedApplication.networkActivityIndicatorVisible = NO;

works the same with an IBOutlet UIActivityIndicator

4)   UISearchBar

UISearchBarDelegate, UISearchDisplayDelegate

@property (strong,nonatomic) NSMutableArray *filteredResultsArray;

@property (strong,nonatomic) IBOutlet UISearchBar *resultsSearchBar;

//UISearch in INIT or LOAD method

// Initialize the filteredResults array with its count of Locations NSManagedObjects

self.filteredResultsArray = [NSMutableArray arrayWithCapacity:[self.originalArray count]];

//ios6 refresh control ONLY

if ([UIRefreshControl class]) {

self.refreshControl = [[UIRefreshControl alloc] init];

[self.refreshControl addTarget:self action:@selector(reload) forControlEvents:UIControlEventValueChanged];

[self reload];

[self.refreshControl beginRefreshing];

} else {

//do nothing



if (tableView == self.searchDisplayController.searchResultsTableView) {

return [filteredResultsArray count];

} else {

return [self.originalArray count];



if (tableView == self.searchDisplayController.searchResultsTableView) {

// IF ITS A SEARCH TABLE…>>>>>>>>>>

//Use filteredResultsArray data

} else {

//Otherwise use self.originalArray


5)   Reminders & Events



#import <EventKit/EventKit.h>





static EKEventStore* eStore = NULL;


//keep a static instance of eventStore

if (!eStore) {

eStore = [[EKEventStore alloc] init];


return eStore;




EKEventStore *store = [self eventStore];

//1 fetch the local event store source

EKSource* localSource = nil;

for (EKSource* src in store.sources) {

if (src.sourceType == EKSourceTypeCalDAV) {

localSource = src;


if (src.sourceType == EKSourceTypeLocal && localSource==nil) {

localSource = src;



if (!localSource) return nil;


EKCalendar* newCalendar = [EKCalendar calendarWithEventStore: store];

newCalendar.title = kAppCalendarTitle;

newCalendar.source = localSource;

newCalendar.CGColor = [[UIColor colorWithRed:0.8 green:0.2 blue:0.6 alpha:1] CGColor];

//3 save the calendar in the event store

NSError* error = nil;

[store saveCalendar: newCalendar commit:YES error:&error];

if (!error) {

return nil;


//4 store the calendar id

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];

[prefs setValue:newCalendar.calendarIdentifier forKey:@”appCalendar”];

[prefs synchronize]; return newCalendar;




EKCalendar* result = nil;

EKEventStore *store = [self eventStore];

//2 check for a persisted calendar id

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];

NSString *calendarId = [prefs stringForKey:@”appCalendar”];


if (calendarId && (result = [store calendarWithIdentifier: calendarId])) {

return result;


//4 check if calendar name exists

for (EKCalendar* cal in store.calendars) {

if ([cal.title compare: kAppCalendarTitle]==NSOrderedSame) {

if (cal.immutable == NO) {

[prefs setValue:cal.calendarIdentifier

forKey:@”appCalendar”]; [prefs synchronize]; return cal;




//5 if no calendar is found whatsoever, create one

result = [self createAppCalendar];


return result;



-(void)addItem:(NSDictionary*)item toCalendar:(EKCalendar*)calendar{

EKEvent* event = [EKEvent eventWithEventStore:[AppCalendar eventStore]];

event.calendar = calendar;

EKAlarm* myAlarm = [EKAlarm alarmWithRelativeOffset: – 06*60 ];

[event addAlarm: myAlarm];

NSDateFormatter* frm = [[NSDateFormatter alloc] init];

[frm setDateFormat:@”MM/dd/yyyy HH:mm zzz”];

[frm setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@”en_US”]];

event.startDate = [frm dateFromString:[show objectForKey:@”startDate”]];

event.endDate = [frm dateFromString:[show objectForKey:@”endDate”]];

event.title = [item objectForKey:@”title”];

event.URL = [NSURL URLWithString:[item objectForKey:@”url”]];

event.location = @”My Office”;

event.notes = [item objectForKey:@”tip”];

//add recurrence

NSNumber* weekDay = [item objectForKey:@”dayOfTheWeek”];

EKRecurrenceDayOfWeek* itemDay = [EKRecurrenceDayOfWeek dayOfWeek: [weekDay intValue]];

EKRecurrenceEnd* runFor3Months = [EKRecurrenceEnd recurrenceEndWithOccurrenceCount:12];

EKRecurrenceRule* myReccurrence = [[EKRecurrenceRule alloc] initRecurrenceWithFrequency:EKRecurrenceFrequencyWeekly interval:1

daysOfTheWeek:[NSArray arrayWithObject:itemDay] daysOfTheMonth:nil monthsOfTheYear:nil weeksOfTheYear:nil daysOfTheYear:nil setPositions:nil end:runFor3Months];

[event addRecurrenceRule: myReccurrence];

//1 save the event to the calendar

NSError* error = nil;

[[AppCalendar eventStore] saveEvent:event span:EKSpanFutureEvents commit:YES error:&error];

//2 show the edit event dialogue

EKEventEditViewController* editEvent = [[EKEventEditViewController alloc] init];

editEvent.eventStore = [AppCalendar eventStore]; editEvent.event = event;

editEvent.editViewDelegate = self;

[self presentViewController:editEvent animated:YES completion:^{

UINavigationItem* item = [editEvent.navigationBar.items objectAtIndex:0]; item.leftBarButtonItem = nil;





– (id) init {

self = [super init];

if (self) {

_eventStore = [[EKEventStore alloc] init];

[_eventStore requestAccessToEntityType:EKEntityTypeEvent

completion:^(BOOL granted, NSError *error) {

if (granted) {

_eventAccess = YES;

} else {

NSLog(@”Event access not granted: %@”, error);



[_eventStore requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted, NSError *error) {

if (granted) { _reminderAccess = YES;

} else {

NSLog(@”Reminder access not granted: %@”, error);



//Initialize the dispatch queue

_fetchQueue = dispatch_queue_create(“com.santiapps.fetchQueue”, DISPATCH_QUEUE_SERIAL);


return self;



NSArray * allCalendars = [_eventStore calendarsForEntityType:EKEntityMaskEvent |

NSMutableArray * writableCalendars = [NSMutableArray array]; for (EKCalendar * calendar in allCalendars) {

if (calendar.allowsContentModifications) { [writableCalendars addObject:calendar];

} }

EKCalendar *calendar = eventStore.defaultCalendarForNewEvents;



EKEvent *event = [EKEvent eventWithEventStore:eventStore]; event.title = @”Hello world!”;
event.startDate = startDate;
event.endDate = endDate;

EKAlarm *alarm = [EKAlarm alarmWithRelativeOffset:-1800]; [event addAlarm:alarm];

event.calendar = eventStore.defaultCalendarForNewEvents;


NSError *err;
BOOL saved = [eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&err];

if (!saved) {
NSLog(@”Error creating the event”);




EKReminder *reminder = [EKReminder reminderWithEventStore:eventStore];

reminder.title = @”Creating my first reminder”; reminder.calendar = [eventStore defaultCalendarForNewReminders];

NSCalendar *calendar =
[NSCalendar currentCalendar];

NSUInteger unitFlags = NSEraCalendarUnit |

NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;

NSDateComponents *dueDateComponents = [calendar components:unitFlags fromDate:dueDate];

//1.5. Set the due date

reminder.dueDateComponents = dueDateComponents;


NSError *err;

BOOL success =

[eventStore saveReminder:reminder commit:YES error:&err];

if (!success) {
NSLog(@”Error creating reminder”);


6)   Local Notifications

//test notif

NSDate *date = [NSDate dateWithTimeIntervalSinceNow:10];

UILocalNotification *localNotification = [[UILocalNotification alloc] init];

localNotification.fireDate = date;

localNotification.timeZone = [NSTimeZone defaultTimeZone];

localNotification.alertBody = @”I am a local notification!”;

localNotification.soundName = UILocalNotificationDefaultSoundName;

[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];

7)   Sort NSArrays for tableviews


NSSortDescriptor *sortDescriptor;

sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@”distance” ascending:YES] autorelease];

NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

NSArray *sortedArray;

sortedArray = [self.annotationsToSort sortedArrayUsingDescriptors:sortDescriptors];

self.annotationsToSort = [(NSArray*)sortedArray mutableCopy];

[self.tableView performSelector:@selector(reloadData) withObject:nil afterDelay:0.5];


8)   Contacts

// Read Contact list xml formatted (Array of Dictionaries)

//read directory here

dispatch_async(kBgQueue , ^{

contacts = [NSArray arrayWithContentsOfURL: kContactsList];

dispatch_async(dispatch_get_main_queue(), ^{

[self.tableView reloadData]; });


// Do this


dispatch_async(kBgQueue , ^{

NSString* request = [NSString stringWithFormat:@”%@?%@”, kContactsList, ids]; //1

NSData *responseData = [NSData dataWithContentsOfURL:[NSURL URLWithString:request]]; //2

//parse vCard data

ABAddressBookRef addressBook = ABAddressBookCreate(); //1

ABRecordRef record = ABPersonCreate(); //2

NSArray* importedPeople = (__bridge_transfer NSArray*)

ABPersonCreatePeopleInSourceWithVCardRepresentation( record, (__bridge CFDataRef)responseData); //3

CFBridgingRelease(record); //4

//define few constants

__block NSMutableString* message = [NSMutableString stringWithString:

@”Contacts imported AB. Add them in Facebook: “];

NSString* serviceKey = (NSString*)kABPersonSocialProfileServiceKey;

NSString* facebookValue = (NSString*)


NSString* usernameKey = (NSString*)kABPersonSocialProfileUsernameKey;

//loop over people and get their facebook

for (int i=0;i<[importedPeople count];i++) { //1

ABRecordRef personRef = (__bridge ABRecordRef) [importedPeople objectAtIndex:i];

ABAddressBookAddRecord(addressBook, personRef, nil);


ABMultiValueRef profilesRef = ABRecordCopyValue( personRef, kABPersonSocialProfileProperty);

NSArray* profiles = (__bridge_transfer NSArray*) ABMultiValueCopyArrayOfAllValues(profilesRef);


for (NSDictionary* profile in profiles) { //4

NSString* curServiceValue = [profile objectForKey:serviceKey]; //5

if ([facebookValue compare: curServiceValue] == NSOrderedSame) { //6

[message appendFormat: @”%@, “, [profile objectForKey: usernameKey]];






//save to addressbook

ABAddressBookSave(addressBook, nil);


//show done alert

dispatch_async(dispatch_get_main_queue(), ^{ [[[UIAlertView alloc]

initWithTitle: @”Done!” message: message

delegate: nil cancelButtonTitle:@”OK” otherButtonTitles:nil] show];



9)   Mapkit



BOOL locationAllowed = [CLLocationManager locationServicesEnabled];

if (locationAllowed==NO) {

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@”Location Service Disabled”

message:@”Re-enable in Settings for this app.”




[alert show];

[alert release];





locationManager = [[CLLocationManager alloc] init];

locationManager.delegate = self;

locationManager.distanceFilter = 10;

locationManager.desiredAccuracy = kCLLocationAccuracyBest;

[locationManager startUpdatingLocation];

//- (void)startMonitoringSignificantLocationChanges

_mapView.showsUserLocation = YES;


-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {

self.userLocation = [locations lastObject];

NSLog(@”userLocation is %f, %f”, self.userLocation.coordinate.latitude, self.userLocation.coordinate.longitude);

CLLocationCoordinate2D zoomLocation;

zoomLocation.latitude = self.userLocation.coordinate.latitude;

zoomLocation.longitude = self.userLocation.coordinate.longitude;

NSLog(@”Using %g,%g”, zoomLocation.latitude, zoomLocation.longitude);

//StopUpdating Location so it wont change all the time

[locationManager stopUpdatingLocation];



CLLocation *pinLocation = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude longitude:annotation.coordinate.longitude];

CLLocationDistance calculatedDistance = [pinLocation distanceFromLocation:self.userLocation];

annotation.distance = calculatedDistance/1000;



//Clean out old annotations

for (id<MKAnnotation> annotation in _mapView.annotations) {

[_mapView removeAnnotation:annotation];



//NSLog(@”self.myLocationsToSort %@”, self.myLocationsToSort);

for (MyLocation *annotation in self.myLocationsToSort) {

//Add annotation to mapview

[_mapView addAnnotation:annotation];



– (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {

static NSString *identifier = @”MyLocation”;

if ([annotation isKindOfClass:[MyLocation class]]) {

//test if mapviewnil

if (_mapView == nil) {



MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];

if (annotationView == nil) {

annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];

annotationView.enabled = YES;

annotationView.canShowCallout = YES;

annotationView.image=[UIImage imageNamed:@”arrest.png”];

} else {

annotationView.annotation = annotation;


//instatiate a detail-disclosure button and set it to appear on right side of annotation

UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

//[infoButton addTarget:self action:@selector(showDetailView:annotationView.annotation) forControlEvents:UIControlEventTouchUpInside];

annotationView.rightCalloutAccessoryView = infoButton;

return annotationView;


return nil;




– (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {

// We have location, do your logic of setting the map region here.

CLLocationCoordinate2D zoomLocation;

NSLog(@”location in FirstVC %@”, self.userLocation);

//Test if userLocation has a value


zoomLocation.latitude = self.userLocation.coordinate.latitude;

zoomLocation.longitude = self.userLocation.coordinate.longitude;

CLLocationDistance visibleDistance = 5000; // 5 kilometers

MKCoordinateRegion adjustedRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, visibleDistance, visibleDistance);

[_mapView setRegion:adjustedRegion animated:YES];



//Called when disclosure tapped

– (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control{

if (![view.annotation isKindOfClass:[MyLocation class]])


// use the annotation view as the sender

[self performSegueWithIdentifier:@”DetailVC” sender:view];


10)                  UICustomization/Appearance

[[UINavigationBar appearance] setShadowImage:[[UIImage alloc] init]];

[self.tabBarItem setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont fontWithName:@”Futura” size:10.0f], UITextAttributeFont, nil] forState:UIControlStateNormal];

UIImage *gradientImage32 = [[UIImage imageNamed:@”FirstCellLogo.png”] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];

[[UINavigationBar appearance] setBackgroundImage:gradientImage32 forBarMetrics:UIBarMetricsDefault];

[self.tabBarItem setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont fontWithName:@”Futura” size:10.0f], UITextAttributeFont, nil] forState:UIControlStateNormal];

[[UITabBar appearance] setSelectedImageTintColor:[UIColor redColor]];

11)                  LetterPress Effect

//letterpress effect the label


NSMutableAttributedString *restName = [[NSMutableAttributedString alloc] initWithString:self.attributionText.text];

[restName addAttributes:@{ NSTextEffectAttributeName : NSTextEffectLetterpressStyle, NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline] } range:NSMakeRange(0, restName.length)];

self.attributionText.attributedText = restName;

12)                  UIGesture

13)                  iCloud

14)                  Library.a

15)                  Instruments

16)                  Checklist App

17)                  UICollectionView & UIContainerView & SplitVC & Popover

18)                  SlideUp

19)                  Raised Tabbar

20)                  Passbook

21)                  AR

22)                  Export Data

23)                  TF

24)                  iAds & AppiRater

25)                  TimeCmoparator – String Parsing

26)                  UIApplicationDelegate sharedApplication & its methods

27)                  NSUserDefaults

// call the store object

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];

// set an object for it

[prefs setObject:imageView.image forKey:@”keyToLookupImage”];

// call sync to save it

[prefs synchronize];

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];

UIImage *retrievedImage = [prefs stringForKey:@”keyToLookupImage”];

imageView.image = retrievedImage;

28)                  Façade design pattern

29)                  Protocols & Delegates

30)                  InAppPurchases

31)                  Datepicker/uipicker

32)                  NSOperation

33)                  Date Formatter

NSDate *date = [NSDate date];

NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];

[dateFormatter setDateStyle:NSDateFormatterShortStyle];

[dateFormatter setTimeStyle:NSDateFormatterFullStyle];

NSString *formattedDateString = [dateFormatter stringFromDate:date];

NSLog(@”formattedDateString for locale %@: %@”,

[[dateFormatter locale] localeIdentifier], formattedDateString);

timeLabel.text = [dateFormatter stringFromDate:date];

34)                  Letterpress Effect

35)                  asd

First Google Glass App – Part 8 – Hello Glass!

Jumping right in, let’s create a Glass GDK project from scratch:

  1. Create New Android Project
  2. Configure GDK
  3. Imports
  4. Code
  5. qwe

To create a new project…See our Part 1 of the tutorial.

Make sure to configure the Glass GDK Sneak Peek Manually if it didn’t get configured by Android Studio or Eclipse on set up.  As it turns out, even if you create a project setting GDK as the Compile for API, it doesn’t get created as such.  You must double check in your build.gradle file (CAREFUL, there are 2 such files.  You need to modify your inner most gradle file) and make sure it looks something like this:

Google Glass GDK App Build Gradle File Settings by Marcio Valenzuela
Google Glass GDK App Build Gradle File Settings by Marcio Valenzuela

And you need to make sure that Android 4.0.3 GDK Sneak Peek & gdk.jar got added to your External Libraries as well.

Ok, once we have that out of the way, we need to include some imports.  In this case we need to add AudioManager support because we will be working with audio.  We also need TextToSpeech for recognizing commands and KeyEvent to respond to touches.

Add the following imports:

import android.content.Context;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.view.View;
import android.view.KeyEvent;
import android.widget.TextView;


We will create the card and its view as well as add a TextView, nothing new here.  But we will create a TextToSpeech variable as well as a context.  We init our speech engine and pass it the value to be speak.

We will also be creating an onKeyDown method to respond to taps on the touchpad.  When they DO occur we will then create an AudioManager to play a tap sound, set the text view and also set speak a new value.

So lets add the following code:

public class HelloGlassActivity extends Activity {

private Card _card;
private View _cardView;
private TextView _statusTextView;

private TextToSpeech _speech;

private Context _context = this;

protected void onCreate(Bundle savedInstanceState) {

// Init TextToSpeech engine
_speech = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
public void onInit(int status) {
_speech.speak(“Hello Glass”, TextToSpeech.QUEUE_FLUSH, null);

// An alternative way to layout the UX
_statusTextView = (TextView)findViewById(;

* Handle the tap from the touchpad.
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
// Handle tap events.
case KeyEvent.KEYCODE_ENTER:

// Status message below the main text in the alternative UX layout
AudioManager audio = (AudioManager)getSystemService(Context.AUDIO_SERVICE);


_speech.speak(“Touchpad touched”, TextToSpeech.QUEUE_FLUSH, null);

return true;
return super.onKeyDown(keyCode, event);

public void onResume() {

public void onPause() {

public void onDestroy() {

Its quite a simple app but it gets your juices flowing!

Plug in your Glass device and hit the Run button!