Update JSON data in tableview properly - objective-c

Iam having a hard time updating my tableview with new results when the user slides to update (UIRefreshControl). The controller works properly, but the data never gets updated. I've tried to wipe the raw-data variable, and my NSArray that holds all the data, but it doesn't seem to work. Iam new to iPhone programming, so forgive me is this is a dumb question.
If I managed to fixed it, wouldn't it be wrong to remove all the data I've already pulled? Is there a simple way to append changes, considering most of my users will be using 3G/Edge connections. Here's my implementation class for the TableViewController:
#import "Nyhetsfane.h"
#interface Nyhetsfane ()
#end
#implementation Nyhetsfane
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Kaller på slide to update.
[self updateTable];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(updateTable) forControlEvents:UIControlEventValueChanged];
[refreshControl setAttributedTitle:[[NSAttributedString alloc] initWithString:#"Dra for å oppdatere"]];
self.refreshControl = refreshControl;
}
- (void)updateTable{
// Viser "spinner" for å symbolisere nettverkstrafikk.
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// URL til JSON filen
NSURL *newsUrl = [NSURL URLWithString:#"http://localhost:7192/fadderapp/events.json"];
//URL Requestobjekt for å kontrollere tilkobling
NSURLRequest *newsRequest = [NSURLRequest requestWithURL:newsUrl];
[[NSURLConnection alloc]initWithRequest:newsRequest delegate:self];
[self.tableView reloadData];
[self.refreshControl endRefreshing];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[newsRawData setLength:0];
newsRawData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[newsRawData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
newsCases = [NSJSONSerialization JSONObjectWithData:newsRawData options:0 error:0];
[self.tableView reloadData];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
UIAlertView *errorView = [[UIAlertView alloc]initWithTitle:#"Feil" message:#"Det har oppstått en feil ved nedlastingen av data. Dobbeltsjekk at du er koblet til internett" delegate:nil cancelButtonTitle:#"Fortsett" otherButtonTitles:nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [newsCases count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
cell.textLabel.text = [[newsCases objectAtIndex:indexPath.row]objectForKey:#"navn"];
return cell;
}
...
For all it's worth, here's my JSON feed:
[
{"navn": "Registration", "tidspunkt": "Monday 15:05", "beskrivelse": "Demo!"},
{"navn": "Party!", "tidspunkt": "Monday 19:30", "beskrivelse": "Demo"}
]

Try with this code
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
newCases = [NSArray array];
newsCases = [NSJSONSerialization JSONObjectWithData:newsRawData options:0 error:0];
[self.tableView reloadData];
}

The proper way to update a table view is to call
[self.tableView reloadData];
It should call all its datasource methods again automatically.

Related

When I touch in tableview How to get all values Back in tableview in search

I trying to search a particular name in an array, It is working well, But I want to cancel search by touching in other place in tableview, How to do that.
I trying to search a particular name in an array, It is working well, But I want to cancel search by touching in other place in tableview, How to do that.
- (void)viewDidLoad {
[super viewDidLoad];
// arr1=[[NSMutableArray alloc]initWithObjects:#"Raj",#"Ramu",#"Abdul",#"Kavitha",#"Abi",#"Abinesh",#"Gobi",#"Giri",#"Gayathri",#"Ramesh",#"Thiru",#"Sri",#"Siva",#"Senthil",#"Kumar",#"Rajkumar",#"Raman",#"Karthik",#"Kanna",#"Kamal",#"Ramya",#"Somu",#"Sankar",#"Murali",#"Muthu",#"Murugan",#"Nandha",#"Kamal", nil];
// NSLog(#"%#",arr1);
NSURL *url=[NSURL URLWithString:#"http://192.168.1.92/Abdul/Json/Json5.txt"];
NSURLRequest *req=[NSURLRequest requestWithURL:url];
conn=[NSURLConnection connectionWithRequest:req delegate:self];
if(conn)
{
webdata =[[NSMutableData alloc]init];
NSLog(#"Connection Success");
}
//[tabvw reloadData];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[webdata setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[webdata appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(#"%#",#"Fail");
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
jsonarr=[NSJSONSerialization JSONObjectWithData:webdata options:0 error:nil];
if (jsonarr> 0)
{
[tabvw reloadData];
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (isfiltered)
{
return [filterarr count];
}
else
{
return [jsonarr count];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:#"myid"];
if (cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"myid"];
}
if (isfiltered ) {
dic =[filterarr objectAtIndex:indexPath.row];
cell.textLabel.text=[dic objectForKey:#"Name"];
}
else
{
dic =[jsonarr objectAtIndex:indexPath.row];
cell.textLabel.text=[dic objectForKey:#"Name"];
}
return cell;
}
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
NSPredicate *pred =[NSPredicate predicateWithFormat:#"Name contains[c]%#",searchText];
filterarr = [jsonarr filteredArrayUsingPredicate:pred];
NSLog(#"%#",filterarr);
isfiltered=YES;
[tabvw reloadData];
}
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
[sbar resignFirstResponder];
}
let's try this and check output,
ViewDidLoad
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(refreshData:)];
tapGesture.delegate = self;
[self.view addGestureRecognizer:tapGesture];
#pragma mark Gesture delegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if (touch.view == self.view)
return YES;
return NO;
}
- (IBAction)refreshData:(id)sender
{
isfiltered=NO;
[tabvw reloadData];
}

Access another top-level JSON object with Objective-C

Iam having a hard time accessing another top-level JSON object within my application.
The plan is to load data from Instagram (which works), but not to count the top-level I want.
The JSON document can be found here (http://pastebin.com/0Z4vBjRn) Basically it has three top-level objects: pagination, meta and data (where I want the data bit).
This is my code for now:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// Viser "spinner" for å symbolisere nettverkstrafikk.
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// URL til JSON filen
NSURL *newsUrl = [NSURL URLWithString:#"https://api.instagram.com/v1/tags/beer/media/recent?client_id=client_key"];
//URL Requestobjekt for å kontrollere tilkobling
NSURLRequest *newsRequest = [NSURLRequest requestWithURL:newsUrl];
[[NSURLConnection alloc]initWithRequest:newsRequest delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[rawImages setLength:0];
rawImages = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[rawImages appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
images = [[NSArray alloc]init]; // Updated
images = [NSJSONSerialization JSONObjectWithData:rawImages options:0 error:0];
[self.collectionView reloadData];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
UIAlertView *errorView = [[UIAlertView alloc]initWithTitle:#"Feil" message:#"Det har oppstått en feil ved nedlastingen av data. Dobbeltsjekk at du er koblet til internett" delegate:nil cancelButtonTitle:#"Fortsett" otherButtonTitles:nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [images count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCelle *cell = (UICollectionViewCelle *)[collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
cell.imageView.image = [UIImage imageNamed:#"eksempel.jpg"];
return cell;
}
Obviously the count part won't work (it only returns three). But how could I make it count all the objects within the "data" object?
All help are highly appreciated! I've done my Googling but I can't seem to find exactly what Iam looking.

[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance

I am trying to parse a Json file into the Table view and I am getting this error
[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance
and the app is crashing. Please help me, I am new to iOS development.
My Code
#implementation ViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
self.title = #"Feeds";
[super viewDidLoad];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"http://little-people.blogspot.com/feeds/posts /default?alt=json"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
data = [[NSMutableData alloc] init];
NSLog(#"Data Data , %#", data);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData
{
[data appendData:theData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
feed = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(#"Data , %#", feed);
[mainTableView reloadData];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"The download could not complete - 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 [feed count];
NSLog(#"Data Data , %#", feed);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MainCell"];
}
if (([feed count] - 1) >=indexPath.row) {
cell.textLabel.text = [[feed objectAtIndex:indexPath.row] objectForKey:#"feed"];
cell.detailTextLabel.text = [[feed objectAtIndex:indexPath.row] objectForKey:#"title"];
}
return cell;
}
The problem is that feed is not a NSArray, but a NSDictionary.
Looking at the JSON, you likely want to access this array: [feed objectForKey:#"entry"]
The top level object in your feed is a JSON object, not a JSON array. So the deserialisation gives you an NSDictionary, not an NSArray.

Reloading a table view after NSURLConnection succeeds

I'm new to Xcode, so bear with me:
I have a table view that I'm trying to reload once the NSURLConnection succeeds. I have a number of messages that help me guide me along the way... but when I call the reload upon the table view, the table doesn't repopulate.
JsonViewController.h:
#import <UIKit/UIKit.h>
#interface JsonViewController : UITableViewController {
NSMutableArray *theTweets;
IBOutlet UITableView *tview;
NSMutableData *responseData;
}
#property (nonatomic, retain) NSMutableArray *theTweets;
#property (nonatomic, retain) UITableView *tview;
#end
JsonViewController.m:
#import "JsonViewController.h"
#import "SBJson.h"
#implementation JsonViewController
#synthesize theTweets;
#synthesize tview;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void) dealloc {
[theTweets release];
[super dealloc];
}
- (NSMutableArray*)theTweets {
return [[theTweets retain] autorelease];
}
- (void) setTheTweets:(NSMutableArray *)newTweets {
if (newTweets != theTweets) {
[newTweets retain];
[theTweets release];
theTweets = newTweets;
NSLog(#"Setting new tweets...");
[tview reloadData];
}
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
tview.delegate = self;
responseData = [[NSMutableData data] retain];
theTweets = [NSMutableArray array];
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:#"http://search.twitter.com/search.json?q=AriaPoker&result_type=recent"]];
[[NSURLConnection alloc] initWithRequest: request delegate:self];
NSLog(#"Trying to get feed upon initialization");
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
// methods that are not important
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSLog(#"Number of the tweets count at this point: %d", [theTweets count]);
return [theTweets count];
}
- (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] autorelease];
}
NSLog(#"Number of the tweets count at this point: %d", [theTweets count]);
// Configure the cell...
NSDictionary *aTweet = [theTweets objectAtIndex:[indexPath row]];
//cell.textLabel.text = [aTweet objectForKey:#"text"];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.font = [UIFont systemFontOfSize:12];
cell.textLabel.numberOfLines = 4;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.text = #"Test";
cell.detailTextLabel.text = #"haha";
//NSURL *url = [NSURL URLWithString:[aTweet objectForKey:#"profile_image_url"]];
//NSData *data = [NSData dataWithContentsOfURL:url];
//cell.imageView.image = [UIImage imageWithData:data];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
NSLog(#"Loading cells in table");
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
}
#pragma mark NSURLConnection Delegate Methods
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
//do nothing
NSLog(#"A connection error has occurred!");
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
NSDictionary *results = [[responseString JSONValue] retain];
NSLog(#"Number of Rows: %d", [results count]);
NSMutableArray *allTweets = [results objectForKey:#"results"];
//[viewController setTweets:allTweets];
theTweets = allTweets;
NSLog(#"Number of misc2: %d", [theTweets count]);
[results release];
[tview reloadData];
}
#end
I'm wondering what I'm doing wrong here.
In connectionDidFinishLoading change from this:
theTweets = allTweets;
to this:
self.theTweets = allTweets;
or this way if you prefer:
[self setTheTweets:allTweets];
You weren't invoking the setter method, so it wasn't getting retained.
As suggested by progrmr try to call the setter method, or simply change definition of theTweets property to #dynamic theTweets in this case when you try to set property, the custom setter method will be called.

Returned web service data not populating tableview

Hey, I cant seem why this code is not working? I am trying to add my returned data from a web service into the uitableview, however failing miserably. The table shows up blank everytime. It seems it doesnt like the cellForRowAtIndexPath method. But honestly I am not sure. I cant spot it for nothing. Please help. Thanks!
#import "RSSTableViewController.h"
#implementation RSSTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
if (self = [super initWithStyle:style]) {
songs = [[NSMutableArray alloc] init];
}
return self;
}
- (void)loadSongs
{
[songs removeAllObjects];
[[self tableView] reloadData];
// Construct the web service URL
NSURL *url =[NSURL URLWithString:#"http://localhost/get_params"];
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:30];
if (connectionInProgress) {
[connectionInProgress cancel];
[connectionInProgress release];
}
[xmlData release];
xmlData = [[NSMutableData alloc] init];
connectionInProgress = [[NSURLConnection alloc] initWithRequest:request
delegate:self];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self loadSongs];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[xmlData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[connection release];
NSString *responseString = [[NSString alloc] initWithData:xmlData encoding:NSUTF8StringEncoding];
songs = [responseString componentsSeparatedByString:#","];
newSongs = [[NSMutableArray alloc] init];
for(int i=0; i < [songs count]; i++) {
[newSongs addObject:[songs:i]]);
}
[songs autorelease];
[[self tableView] reloadData];
//
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
[connectionInProgress release];
connectionInProgress = nil;
[xmlData release];
xmlData = nil;
NSString *errorString = [NSString stringWithFormat:#"Fetch failed: %#",
[error localizedDescription]];
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:errorString
delegate:nil
cancelButtonTitle:#"OK"
destructiveButtonTitle:nil
otherButtonTitles:nil];
[actionSheet showInView:[[self view] window]];
[actionSheet autorelease];
[[self tableView] reloadData];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[super dealloc];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [newSongs count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"UITableViewCell"] autorelease];
}
[[cell textLabel] setText:[newSongs objectAtIndex:[indexPath row]]];
return cell;
}
#end
It appears you're ignoring warning messages, which is a no-no in Objective-C. The following code can't possibly work:
[newSongs addObject:[songs:i]]
What you probably meant to write was something like this:
[newSongs addObject:[songs objectAtIndex:i]]
But instead of doing all this:
newSongs = [[NSMutableArray alloc] init];
for(int i=0; i < [songs count]; i++) {
[newSongs addObject:[songs:i]]);
}
why not just do this?
newSongs = [songs mutableCopy];