tenqyu web service to device
DESCRIPTION
This presentation describes how to get data from the Tenqyu webservice (www.tenqyu.com) to via JSON to the iPhone device.TRANSCRIPT
for pleasant living
From MongoDB via JSON to UITableview
...and back
February 2012
Saturday, February 11, 12
for pleasant living
Introduction
What was the problem that I needed to solve?
1.Massive data (MongoDB)
2.Consistent way to communicate with the user(TableView)
3.Design changes and data upgrades (CoreData)
4.Simple and light data exchange(JSON)
Saturday, February 11, 12
for pleasant living
Application flow
MongoDBPHPJSON
CoreDataUITable
Player collection
Notification collection
Mongo Driver
Server side
Communicationinterface
Native BSONformat
Lightexchangeprotocol
Data Management
SQLite support
Difficult to learn
Known UX
No Training
Email paradigm
Master/Detail
Saturday, February 11, 12
for pleasant living
The iPhone side
We need to cover 3 areas
1. Connection to the web service
2. Transformation into CoreData
3. Presentation for TableView
Saturday, February 11, 12
for pleasant living
ViewController
Infrastructure overview
How are the different parts supposed to co-exist?IBOutlet UITableView* newsTable;
IBOutlet UITableViewCell *tblCell;
NSFetchedResultsController *fetchedResultsController;!NSManagedObjectContext *managedObjectContext;
UITableView
WebAccess
configureCell
cellForRowAtIndexPath
NSFetchedResultsController
didChangeObject
2. connectionDidFinishLoadingnotificationsReceived
findOrCreateNews- (BOOL) findOrCreateNews : (NSDictionary *) dic inManagedObjectContext:(NSManagedObjectContext *) context ;
Implements the protocolfunction
notificationsReceived
QyuWebDelegate (@Protocol of WebAccess)UITableViewDelegateUITableViewDataSourceNSFetchedResultsControllerDelegate
calls
calls
Initiate Object1. updateNews
calls
Delegatelist
Saturday, February 11, 12
for pleasant living
if (qyuDelegate.updateNotification==TRUE) { NSLog(@"Trying to update"); QyuWebAccess *webNotifications = [[QyuWebAccess alloc] initWithConnectionType:@"notify"]; [webNotifications setDelegate:self]; [webNotifications updateNews:qyuDelegate.usrQyu.mongoId]; }
Web Service Connection
12
3
(2) Simply sets a string to “notify” which is checked during didFinishedLoading
During loading (viewWillAppear)
Saturday, February 11, 12
for pleasant living
Web Service Connection
Best practices : Keep a separate object to organize the WebAccess
Relevant items: 1.A JSON Parser2. A formal protocol spec (delegate pattern)3. The NSURLConnection items (Connection, Data)4. A NSDictionary for the JSON data
https://github.com/stig/json-framework/
Saturday, February 11, 12
for pleasant living
Setting up the connection
NSString *baseURL = @"http://choose.tenqyu.com/notifications.php";
NSString *idstr = [@"id=" stringByAppendingString:@"getNotifications"]; NSString *mongoStr = [@"&mongoId=" stringByAppendingString:mongoId]; NSString *requestVars = [idstr stringByAppendingFormat:@"%@", mongoStr];
NSData *requestData = [NSData dataWithBytes: [requestVars UTF8String] length: [requestVars length]]; // Create the request. NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString: baseURL] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; // create the connection with the request // and start loading the data [theRequest setHTTPMethod: @"POST"]; [theRequest setHTTPBody: requestData]; NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
1. Set the base URL address
2. Set the HTTP POST vars to prepare the data item.
3. Prepare the NSData item and Connection Items
4. Initialize the connection. Results will be in connectionDidFinishedLoading
Saturday, February 11, 12
for pleasant living
Did Finished Loading?
} else if(self.connectionType == @"notify") { NSString *jsonString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding]; self.jsondata = [jsonString JSONValue];
if(delegate && [delegate respondsToSelector:@selector(notificationsReceived:)]) { [delegate notificationsReceived:self.jsondata];
} else {
NSLog(@"Problem with the delegation in connectionDidFinishLoading loading"); }
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
[...]1
3
NSDictionary Object
2
Saturday, February 11, 12
for pleasant living
ViewController
Infrastructure overview
How are the different parts supposed to co-exist?IBOutlet UITableView* newsTable;
IBOutlet UITableViewCell *tblCell;
NSFetchedResultsController *fetchedResultsController;!NSManagedObjectContext *managedObjectContext;
UITableView
WebAccess
configureCell
cellForRowAtIndexPath
NSFetchedResultsController
didChangeObject
2. connectionDidFinishLoadingnotificationsReceived
findOrCreateNews- (BOOL) findOrCreateNews : (NSDictionary *) dic inManagedObjectContext:(NSManagedObjectContext *) context ;
Implements the protocolfunction
notificationsReceived
QyuWebDelegateUITableViewDelegateUITableViewDataSourceNSFetchedResultsControllerDelegate
calls
calls
Initiate Object1. updateNews
calls
Delegatelist
Saturday, February 11, 12
for pleasant living
Delegate has been triggered
- (void)notificationsReceived:(NSDictionary *)resultData{ for (NSDictionary* notification in resultData) {
[self findOrCreateNews:notification inManagedObjectContext:qyuDelegate.managedObjectContext];
} qyuDelegate.updateNotification=FALSE;}
1
2
This function needs to be implemented in the Viewcontroller
Loop over the NSDictionary Items
Upsert the TableViewItems
Saturday, February 11, 12
for pleasant living
CoreData
Core Data is just managing the flow, not storing data
News User
Persistent Store 1
Persistent Store 2
Managed Object Context
ViewController Application Delegate
FetchedResultController
FetchedResultController1 2
SQLiteNews
SQLiteUser
Saturday, February 11, 12
for pleasant living
The “save” in findAndCreateNews
NSFetchRequest *request = [self.fetchedResultsController fetchRequest];! request.entity = [NSEntityDescription entityForName:@"News" inManagedObjectContext:context]; request.predicate = [NSPredicate predicateWithFormat:@"mongoId = %@", nItem.mongoId];
NSError *error = nil; NSArray *items = [[context executeFetchRequest:request error:&error] lastObject]; !!! if (!error && !items && nItem ) { ! ! NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"News" inManagedObjectContext:context];! ! [newManagedObject setValue:nItem.nText forKey:@"nText"];
[...]
! ! [newManagedObject setValue:nItem.mongoId forKey:@"mongoId"];! ! [newManagedObject setValue:[NSDate date] forKey:@"pushDate"];! !! ! NSError* error; Here we now simply save ! !
if (![context save:&error])! ! ! {! ! ! // Handle the error.! ! ! NSLog(@"Unresolved error %@, %@", error, [error userInfo]);! ! ! exit(-1);! ! }!! ! return TRUE;! } else{! !
Saturday, February 11, 12
for pleasant living
ViewController
Infrastructure overview
How are the different parts supposed to co-exist?IBOutlet UITableView* newsTable;
IBOutlet UITableViewCell *tblCell;
NSFetchedResultsController *fetchedResultsController;!NSManagedObjectContext *managedObjectContext;
UITableView
WebAccess
configureCellcellForRowAtIndexPath
NSFetchedResultsController
didChangeObject
2. connectionDidFinishLoadingnotificationsReceived
findOrCreateNews- (BOOL) findOrCreateNews : (NSDictionary *) dic inManagedObjectContext:(NSManagedObjectContext *) context ;
Implements the protocolfunction
notificationsReceived
QyuWebDelegateUITableViewDelegateUITableViewDataSourceNSFetchedResultsControllerDelegate
calls
calls
Initiate Object1. updateNews
calls
Delegatelist
Saturday, February 11, 12
for pleasant living
The TableView
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath{
NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[managedObject valueForKey:@"nText"] description]; cell.detailTextLabel.text = [[managedObject valueForKey:@"longText"] description]; cell.textLabel.font = [UIFont fontWithName:@"ArialRoundedMTBold" size:16];
UIImage *cellicon=[UIImage imageNamed:@"ux1.png"] ; [[cell imageView] setImage:cellicon];
}
1. Retrieve the managedObject from the FetchedResultscontroller
2. Get the “fields” in the managedObject and store them in the cell
Saturday, February 11, 12
for pleasant living
Thank you!
Saturday, February 11, 12