Parse a JSON array of dictionaries in a tableview - iphone

I'm stuck at the point of parsing a JSON array of dicts (http://www.cjs-design.nl/json.php) into a tableview. I just want to display the title's first, ill figure out detailviews later.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSString *rawJson = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:#"http://www.cjs-design.nl/json.php"]];
// No connection or file not found
if ([rawJson length] == 0) {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Foutmelding" message:#"De URL kon niet worden gevonden" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
[alert release];
[rawJson release];
return;
}
SBJSON *parser = [[[SBJSON alloc] init] autorelease];
// 1. get the top level value as a dictionary
NSDictionary *jsonObject = [parser objectWithString:rawJson error:NULL];
// 2. get the object as an array
NSArray *list = [jsonObject objectForKey:#"book"];
// 3. iterate the array; each element is a dictionary.
for (NSDictionary *book in list)
{
// that contains a string for the key "title"
NSString *title = [book objectForKey:#"title"];
cell.textLabel.text = title;
}
return cell;
}

Somewhere i.e. viewDidLoad, you need to parse your JSON. Then implement UITableView's dataSource methods.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [list count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSDictionary *book = [list objectAtIndex:indexPath.row];
NSString *title = [book objectForKey:#"title"];
cell.titleLabel.text = title;
}

- (void)viewDidLoad
{
[super viewDidLoad];
NSString *rawJson = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:#"http://www.cjs-design.nl/json.php"]];
// No connection or file not found
if ([rawJson length] == 0) {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Foutmelding" message:#"De URL kon niet worden gevonden" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
[alert release];
[rawJson release];
return;
}
SBJsonParser *parser = [[SBJsonParser alloc] init];
// 1. get the top level value as a dictionary
NSDictionary *jsonObject = [parser objectWithString:rawJson error:NULL];
NSLog(#"Dict: %#",jsonObject);
list = [jsonObject objectForKey:#"book"];
NSLog(#"List: %#",list);
[rawJson release];
}
When I NSlog them, they both print Null, so the string doesnt get parsed? the string contains a dictionary of arrays tho.

Related

NSJSONSerialization Json Nested Sub

Im trying to get deep into a nested JSon Array, i have successfully done it for the level above but I cant work out how to get any deeper.
I need to log the image #url I have attached a screen show to show where i need it to go.
Thanks :)
- (void)viewDidLoad
{
[super viewDidLoad];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"http://api.storageroomapp.com/accounts/511a4f810f66026b640007b8/collections/511a51580f66023bff000ce9/entries.json?auth_token=Zty6nKsFyqpy7Yp5DP1L&preview_api=1"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
-(void)connectionDidFinishLoading:(NSURLConnection *) connection{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:nil error:nil];
NSDictionary *arrayDictionary = dictionary[#"array"];
news = arrayDictionary[#"resources"];
[tableView reloadData];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"The data could not be downloaded - please make sure you're connected to either 3G or Wi-FI" delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
-(int)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [news count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *newsItem = news[[indexPath row]];
NSString *title = newsItem[#"title"];
NSString *date = newsItem[#"date"];
NSString *thumb = newsItem[#"tablethumb"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MainCell"];
[[cell textLabel] setText:title];
[[cell detailTextLabel] setText:date];
if((NSNull *)thumb == [NSNull null]){
NSLog(#"no image");
} else{
NSLog(# "image = %#", thumb);
}
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
For traversing nested objects you could use valueForKeyPath method and use the dot syntax to drill down the hieararchy.
Something like this would fetch the url value from your newsItem dictionary:
NSDictionary *newsItem = news[[indexPath row]];
NSString *thumbUrl = [newsItem valueForKeyPath:#"tablethumb.url"];
PS. If you really have the properties prefixed by # then you might get into trouble by using valueForKeyPath since # is a special token used as an operator. In this case you could do something like this instead:
NSDictionary *newsItem = news[[indexPath row]];
id tablethumb = [newsItem objectForKey:#"tablethumb"];
NSString *thumbUrl = #"";
// Check if not null and access the #url
if (tablethumb != [NSNull null])
thumbUrl = tablethumb[#"#url"];
Try to access value from dictionary like this,
NSLog(#"URL: %#",[newsItem objectForKey:#"#url"]);

Deleting core data single entry through table iPhone

Using core data to populate my table view. The thing I am not getting is that how can I delete a single entry from the core data.
Here is the code I am using:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == favouritesTable) {
cellValue = [licensePlateArray objectAtIndex:indexPath.row];
} else { // handle search results table view
cellValue = [filteredListItems objectAtIndex:indexPath.row];
}
static NSString *CellIdentifier = #"vlCell";
VehicleListCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSLog(#"Cell Created");
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"VehicleListCell" owner:nil options:nil];
for (id currentObject in nibObjects) {
if ([currentObject isKindOfClass:[VehicleListCell class]]) {
cell = (VehicleListCell *)currentObject;
}
}
UILongPressGestureRecognizer *pressRecongnizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(tableCellPressed:)];
pressRecongnizer.minimumPressDuration = 0.5f;
[cell addGestureRecognizer:pressRecongnizer];
[pressRecongnizer release];
}
cell.textLabel.font = [UIFont systemFontOfSize:10];
Favouritesdata *favdata = [licensePlateArray objectAtIndex:indexPath.row];
[[cell ignition] setImage:[UIImage imageNamed:#"ignition.png"]];
[[cell direction] setImage:[UIImage imageNamed:#"south.png"]];
cell.licPlate.text = [favdata licenseplate];
NSLog(#"cellvalue for cellforRow: %#", cell.licPlate.text);
return cell;}
In the method of UILongPressGestureRecognizer:
- (void)tableCellPressed:(UILongPressGestureRecognizer *)recognizer{
if (recognizer.state != UIGestureRecognizerStateBegan) {
return;
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:nil delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles: nil] ;
[alert addButtonWithTitle:#"Remove from Favourites"];
[alert addButtonWithTitle:#"Take to Map"];
[alert show];}
In alert view method:
-(void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *title = [alert buttonTitleAtIndex:buttonIndex];
NSManagedObjectContext *contextFav = [app managedObjectContext];
Favouritesdata * favourites = [NSEntityDescription insertNewObjectForEntityForName:#"Favouritesdata" inManagedObjectContext:contextFav];
if([title isEqualToString:#"Remove from Favourites"])
{
NSLog(#"cellValueForLongPress: %#", cellValueForLongPress);
if (cellValueForLongPress <= 0) {
NSLog(#"No data to delete");
}
else {
favourites.licenseplate = cellValueForLongPress;
}
[alert dismissWithClickedButtonIndex:0 animated:YES];
}
else if([title isEqualToString:#"Take to Map"])
{
NSLog(#"Go to MapView");
}
NSError *error;
if (![context save:&error]) {
NSLog(#"Error Occured");
}}
If you want to delete managed object from CoreData storage then you should have:
Reference to NSManagedObjectContext from where you will remove object : context
Reference to NSManagedObject that you want to delete: object
Then it will be very simple to remove object:
[context deleteObject:object];
You should know
index of the row to remove, for example, i.
retrieve it from your array: NSObject *object = [licensePlateArray objectAtIndex:i];
remove it from db : [context deleteObject:object];
remove it from array: [licensePlateArray removeObject:object];
You have to identify your NSManagedObject and then call deleteObject on your managedObjectContext. Then this object will be removed from your core data.
But you have to provide a mechanism to "somehow" get the object behind a specific tableview row.

Issue removing core data entry by selecting a row on table view

Using core data to populate my table view. The thing I am not getting is that how can I delete a single entry from the core data.
I am using uitableview not the controller.
Here is the code I am using:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == favouritesTable) {
cellValue = [licensePlateArray objectAtIndex:indexPath.row];
} else { // handle search results table view
cellValue = [filteredListItems objectAtIndex:indexPath.row];
}
static NSString *CellIdentifier = #"vlCell";
VehicleListCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSLog(#"Cell Created");
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"VehicleListCell" owner:nil options:nil];
for (id currentObject in nibObjects) {
if ([currentObject isKindOfClass:[VehicleListCell class]]) {
cell = (VehicleListCell *)currentObject;
}
}
UILongPressGestureRecognizer *pressRecongnizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(tableCellPressed:)];
pressRecongnizer.view.tag = indexPath.row;
pressRecongnizer.minimumPressDuration = 0.5f;
[cell addGestureRecognizer:pressRecongnizer];
[pressRecongnizer release];
}
cell.textLabel.font = [UIFont systemFontOfSize:10];
Favouritesdata *favdata = [licensePlateArray objectAtIndex:indexPath.row];
[[cell ignition] setImage:[UIImage imageNamed:#"ignition.png"]];
[[cell direction] setImage:[UIImage imageNamed:#"south.png"]];
cell.licPlate.text = [favdata licenseplate];
NSLog(#"cellvalue for cellforRow: %#", cell.licPlate.text);
return cell;}
In the method of UILongPressGestureRecognizer:
- (void)tableCellPressed:(UILongPressGestureRecognizer *)recognizer{
if (recognizer.state != UIGestureRecognizerStateBegan) {
return;
}
VehicleListCell* cell = (VehicleListCell *)[recognizer view];
cellValueForLongPress = cell.licPlate.text;
NSLog(#"cell value: %#", cellValueForLongPress);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:nil delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles: nil] ;
alert.tag = recognizer.view.tag;
[alert addButtonWithTitle:#"Remove from Favourites"];
[alert addButtonWithTitle:#"Take to Map"];
[alert show];}
here in alert view method the selected row will be deleted (if([title isEqualToString:#"Remove from Favourites"])):
-(void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *title = [alert buttonTitleAtIndex:buttonIndex];
NSManagedObjectContext *contextFav = [app managedObjectContext];
Favouritesdata * favourites = [NSEntityDescription insertNewObjectForEntityForName:#"Favouritesdata" inManagedObjectContext:contextFav];
if([title isEqualToString:#"Remove from Favourites"])
{
NSLog(#"cellValueForLongPress: %#", cellValueForLongPress);
///////// to remove the object from core data
[licensePlateArray removeObjectAtIndex:alert.tag];
}
else if([title isEqualToString:#"Take to Map"])
{
NSLog(#"Go to MapView");
}
NSError *error;
if (![context save:&error]) {
NSLog(#"Error Occured");
}
[favouritesTable reloadData];}
Write this in cellForRowAtIndexPath
UILongPressGestureRecognizer *pressRecongnizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(tableCellPressed:)];
pressRecongnizer.view.tag = indexPath.row;
pressRecongnizer.minimumPressDuration = 0.5f;
[cell addGestureRecognizer:pressRecongnizer];
[pressRecongnizer release];
and use alertview like this
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:nil delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles: nil] ;
alert.tag = recognizer.view.tag;
[alert addButtonWithTitle:#"Remove from Favourites"];
[alert addButtonWithTitle:#"Take to Map"];
[alert show];
then write this in -(void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex
[YourArray removeObjectAtIndex:alert.tag];
[YourTable reloadData];
Please use this code at appropriate place in your code..
Happy Coding..

changing data in table view on button clicked-iphone

I am new for iPhone apps development.
In my app when i clicked on search button ,i want to display record in table view.
i m using array to change record in table view but its not working..please help
viewController.m
-(IBAction) printButtonPressed : (id) sender
{
mylabel.text =keyfileld.text;
UITableView *tableView ;
NSIndexPath *indexPath;
mylabel.text =keyfileld.text;
NSString *post =[NSString stringWithFormat:#"username=%#",keyfileld.text];
NSString *hostStr = #"http://demo.com/search_iphone.php?";
hostStr = [hostStr stringByAppendingString:post];
NSData *dataURL = [NSData dataWithContentsOfURL: [ NSURL URLWithString: hostStr ]];
NSString *serverOutput = [[NSString alloc] initWithData:dataURL encoding: NSASCIIStringEncoding];
[states removeObjectForKey:#"1"];
[states removeObjectForKey:#"2"];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [datasource objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if(serverOutput)
{
NSArray *listItems = [serverOutput componentsSeparatedByString:#"#"];
UIAlertView *alertsuccess = [[UIAlertView alloc] initWithTitle:#"Congrats" message:#"You are authorized"
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertsuccess show];
mylabel.text = serverOutput;
NSMutableArray *stringArray = [[NSMutableArray alloc] init];
int x=1;
for (int i=0;i<listItems.count; i++)
{
NSString *myString = [NSString stringWithFormat:#"%d",x];
NSArray *listItemsid = [[listItems objectAtIndex:i] componentsSeparatedByString:#","];
NSLog(#"place name at index %d: %#\n", i, [listItemsid objectAtIndex:1]);
[states setObject:[listItemsid objectAtIndex:1] forKey:myString];
x++;
[stringArray insertObject:[NSMutableArray arrayWithObjects:str,nil] atIndex:i];
}
datasource = [states allKeys];
} else {
UIAlertView *alertsuccess = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Username or Password Incorrect"
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertsuccess show];
// [alertsuccess release];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
id aKey = [datasource objectAtIndex:indexPath.row];
cell.textLabel.text = [states objectForKey:aKey];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
Try calling [tableView reloadData]; after loading the new data into the array's...

Custom delete button in uitableview cell don't work

I made tableView with filteredReservations array wich contains Rezervacija objects.
I added custom button "board", and when button is clicked, I ask with alert view to confirm this and then sending request to server. When receive server's response I need to delete row from table and object from filteredReservations array.
When I delete first row it's ok, but after that in filteredReservations instead of Rezervacija object, I got UIButton objects! I don't know HOW :)
Code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return([filteredReservations count]);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
}
Reservation *reservation = [filteredReservations objectAtIndex:indexPath.row];
NSString *label = [[NSString alloc] initWithFormat:#"%# (%d)", reservation.name, reservation.seatsNumber];
cell.textLabel.text = label;
[label release];
[reservation release];
tableView.allowsSelection = FALSE;
UIButton *cellButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[cellButton setFrame:CGRectMake(430.0, 2.0, 106.0, 40.0)];
[cellButton setTitle:#"Board" forState:UIControlStateNormal];
[cellButton addTarget:self action:#selector(BoardPassengers:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:cellButton];
cellButton.tag = indexPath.row;
return cell;
}
-(void)BoardPassengers:(id)sender{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Question" message:#"Do you want to board passengers?"
delegate:self cancelButtonTitle:#"Odustani" otherButtonTitles:#"Da", nil];
[alert show];
[alert release];
passengerForBoarding = [NSIndexPath indexPathForRow:((UIControl*)sender).tag inSection:1];
}
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
// the user clicked one of the OK/Cancel buttons
if (buttonIndex == 0)
{
NSLog(#"cancel");
}
else
{
Reservation *reservationNew = [filteredReservations objectAtIndex:passengerForBoarding.row];
NSString *reservationId = [[NSString alloc] initWithFormat:#"%d",reservationNew.reservationId];
params = [NSDictionary dictionaryWithObjectsAndKeys: #"1", #"tour_id", #"1", #"bus_number",reservationId, #"reservation_id", nil];
[[RKClient sharedClient] post:#"/service/boardingToBus.json" params:params delegate:self];
[DSBezelActivityView newActivityViewForView:self.view withLabel:#"Boarding..."];
}
}
- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response {
if([[request resourcePath] isEqualToString:#"/service/boardingToBus.json"]){
if([[response bodyAsString] isEqualToString:#"ERROR"]){
[DSBezelActivityView removeViewAnimated:YES];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:#"Error."
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}else{
[DSBezelActivityView removeViewAnimated:YES];
[filteredReservations removeObjectAtIndex:passengerForBoarding.row];
[self.tableView reloadData];
//[self.tableView beginUpdates];
//[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:passengerForBoarding]
// withRowAnimation:UITableViewRowAnimationFade];
// NSLog(#"%i", passengerForBoarding.row);
//[self.tableView endUpdates];
}
}
}
It sounds like you need to make sure the table view is explicitly aware of how many filtered reservations it needs to display.
// assuming only one section for your table view
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return([filteredReservations count]);
}
For more info:
http://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDataSource_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITableViewDataSource/tableView:numberOfRowsInSection:
Hey you can get the value of "Reservation ID" By this.
-(void)BoardPassengers:(id)sender{
Reservation *reservationNew = [filteredReservations objectAtIndex:[sender tag]];
NSString *reservationId = [NSString StringWithFormat:#"%d",reservationNew.reservationId];}
Or you can use this value anywhere you want like you have mentioned via alert-box.