concurrent networking - made easy
DESCRIPTION
A short presentation we held at the Stockholm CocoaHeads meeting March 5th 2012 on concurrent networking in iOS.TRANSCRIPT
CONCURRENT NETWORKING – MADE EASY!
CocoaHeads Stockholm, March 5 2012MARTHIN FREIJ / AMAZING APPLICATIONS
A two-man army of digital production veterans, on a crusade to delight people with pixel perfect design, delicate code and stunning user experiences.
We work hard to ensure that everything from concept and user interaction design to animations and technical implementation is as sleek as possible.
AMAZING APPLICATIONS / IN SHORT
A tech savvy pixel pusher and design geek with over 15 years of experience working with global brands in digital channels. Also a confused father and a avid gamer.
CLIENT SHORT LIST: Vin & Sprit (Absolut Vodka & Malibu Rum), IKEA, Scania, Electrolux, Nokia, SCA (Libresse)
JIMMY POOPUU / ART DIRECTOR
Has written million lines of code as a software developer and held countless lectures as technical trainer during the past 10 years for clients in the bank, finance and media sector.
CLIENT SHORT LIST: ICA Banken, Handelsbanken, Bonnier, Dagens Nyheter, Dagens Industri
MARTHIN FREIJ / SENIOR DEVELOPER
WKLY GREEN KITCHENNJUICE
CONCURRENT NETWORKING – MADE EASY!
CocoaHeads Stockholm, March 5 2012MARTHIN FREIJ / AMAZING APPLICATIONS
MADE EASY?IS IT HARD IN THE FIRST PLACE?
APPLE PROVIDE SIMPLE API’S FOR NETWORKING
NSURLConnectionNSURLRequestNSURLResponse
FEW DEVELOPERS USE THEM
;(
BECAUSE THEY REQUIRE A LOT OF BOILERPLATE CODE
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate;
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
AND MAYBE YOU WANT TO DO MORE THAN ONE REQUEST
AT THE TIME?
THEN YOU NEED TO KEEP TRACK
OF YOUR REQUESTS AND CONNECTIONS
WE TEND TO USE BOILERPLATE CODE WRITTEN BY SOMEONE ELSE
LIKE NETWORK LIBRARIES
ASIHTTPREQUEST
DOH! DISCONTINUED!
AFNETWORKING
BUGS!RACE CONDITIONS!MEMORY LEAKS!
!
IT TURNS OUT TO BE KIND OF HARD
NEW STUFF IN iOS 5
+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue*) queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*)) handler;
NSURLRequestNSOperationQueueCompletion Handler
☞☞☞
// Create the requestNSURL *url = [NSURL URLWithString:@"https://the.api.com/method/"];NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// Create the queueNSOperationQueue *queue = [[NSOperationQueue alloc] init];queue.name = @"com.your.unique.queue.name";
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { // If there was an error getting the data if (error) { dispatch_async(dispatch_get_main_queue(), ^(void) { // Display error message in UI }); return; } // Do stuff with the data dispatch_async(dispatch_get_main_queue(), ^(void) { // Update UI });}];
ONE MORE THING...
CORE DATA AND CONCURRENCY HAVEN’T ALWAYS BEEN BEST BUDDIES
UNTIL NOW IN iOS 5
- (id)initWithConcurrencyType:(NSManagedObjectContextConcurrencyType)ct;- (void)setParentContext:(NSManagedObjectContext*)parent;- (void)performBlock:(void (^)())block;
NSManagedObjectContext
Set your main context to execute on Main Queue(NSMainQueueConcurrencyType)
☞IMPORT DATA EXAMPLE (1 / 2)
Create an import context and tell Core Data to create a new queue for it (NSPrivateQueueConcurrencyType)
☞Set the main context as the import contexts parentContext☞
On the import context, call performBlock and do the import (i.e. download data, validate it, import it, purge old data etc)
☞IMPORT DATA EXAMPLE (2 / 2)
Save changes on the import context. This will stage it up one level (to the main context)
☞Save changes on the main context. This will persist it on the associated persistent store (and update NSFetchedResultControllers etc)
☞
// Setup the main context (probably in the AppDelegate)[[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
importContext.parentContext = self.managedObjectContext;
[importContext performBlock:^{
// Download data, import etc..
NSError *importError = nil; [importContext save:&importError];
[importContext.parentContext performBlock:^{ NSError *parentError = nil; [importContext.parentContext save:&parentError]; }];}];
THATS IT, THANKS FOR YOUR TIME!
www.amazing-apps.se