Adding twitter search to a custom cell in tableview - objective-c

I have a TWRequest that has created a dictionary output called dict. I would like to output the results of this into a custom cell in a tableView. The trick bit is that each individual tweet is then split (as its 'text' will be split into sections separated by colons) and put into an Array I am struggling with how to take the 'text' component out of the dictionary and apply this to the tableview. Here is my code... Any advise would be greatly appreciated. Thanks in advance.
- (void)fetchTweets
{
// Do a simple search, using the Twitter API
TWRequest *request = [[TWRequest alloc] initWithURL:[NSURL URLWithString:
#"http://search.twitter.com/search.json?q=myhashtagforsearchgoeshere"]
parameters:nil requestMethod:TWRequestMethodGET];
// Notice this is a block, it is the handler to process the response
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if ([urlResponse statusCode] == 200)
{
// The response from Twitter is in JSON format
// Move the response into a dictionary and print
NSError *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
NSLog(#"Twitter response: %#", dict);
}
else
NSLog(#"Twitter error, HTTP response: %i", [urlResponse statusCode]);
}];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"MyCell";
// I'm using a custom cell
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// then I want to grab the text part only from the tweets
NSString *tweetText = [[dict objectForKey:#"text"]objectAtIndex:indexPath.row];
// then I place the output into an array (the tweet is carved up into 3 components separated by a colon
NSArray *tweetComponents = [tweetText componentsSeparatedByString:#":"];
NSLog(#"Tweettext: %#", tweetText);
// then I link this to my labels in my custom cell using objectatindex
cell.myHeader.text = [tweetComponents objectAtIndex:0];
cell.myDetails.text = [tweetComponents objectAtIndex:1];
cell.myDate.text = [tweetComponents objectAtIndex:2];
return cell;
}

Related

Display records of next page in json in uitableview on scrolling the tableView when I reach the last record

I am trying to make an application that uses SBJSON and ASIHTTPRequest containing 273 pages (50 records in each page)in json. When I scroll the tableView I want to get next 50 records when I reach the last record.Currently I am getting only the first 50 records. How will I get all the records? I am using Xcode 6 objective c.
//Here I am taking the json data on view load
- (void)viewDidLoad
{
[super viewDidLoad];
main_array = [[NSMutableArray alloc] init];
NSURL *countryURL = [NSURL URLWithString:#"http://api.worldbank.org/countries/all/indicators/SP.POP.TOTL?format=json"];
ASIHTTPRequest *request = [ASIFormDataRequest requestWithURL:countryURL];
[request setDelegate:self];
[request startSynchronous];
[self setTitle:#"COUNTRIES"];
}
-(void) requestFinished: (ASIHTTPRequest *) request
{
NSString *theJSON = [request responseString];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSMutableArray *jsonDictionary = [parser objectWithString:theJSON error:nil];
//Here I am separating the different arrays and storing it in model class
NSDictionary *pagesDict = [jsonDictionary objectAtIndex:0];
NSMutableArray *dataArray = [jsonDictionary objectAtIndex:1];
for (NSDictionary *dictionary in dataArray)
{
Model *model = [[Model alloc]init];
NSDictionary *tmpdict =[dictionary objectForKey:#"indicator"];
NSDictionary *tmpcountdict =[dictionary objectForKey:#"country"];
model.indicator = [tmpdict objectForKey:#"value"];
model.country = [tmpcountdict objectForKey:#"value"];
model.date = [dictionary objectForKey:#"date"];
model.value = [dictionary objectForKey:#"value"];
model.decimal = [dictionary objectForKey:#"decimal"];
//main_array is the main mutable array to store values of model class
[main_array addObject:model];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [main_array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"SimpleTableViewCell";
SimpleTableViewCell *cell = (SimpleTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
Model *model = [[Model alloc]init];
model = [self.main_array objectAtIndex:indexPath.row];
//Display value in cells
cell.indicatorLabel.text = [NSString stringWithFormat:#"%#",model.indicator];
cell.countryLabel.text = [NSString stringWithFormat:#"%#",model.country];
cell.yearLabel.text = [NSString stringWithFormat:#"%#",model.date];
cell.valueLabel.text = [NSString stringWithFormat:#"%#",model.value];
cell.decimalLabel.text = [NSString stringWithFormat:#"%#",model.decimal];
return cell;
}
Have you tried using ‘page’ parameter in your query?
http://api.worldbank.org/countries/all/indicators/SP.POP.TOTL?format=json&page=2
If you want to list all records, you can use ‘per_page’ parameter, which I would not recommend
http://api.worldbank.org/countries/all/indicators/SP.POP.TOTL?format=json&per_page=13640
You can set some tag on your last cell and then send call to the server once you reach to that cell. Once you received data from server append it to your table view data and reload the data.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"mycell"];
if(indexPath.row == [data count])
{
cell.tag = SOME_TAG_OF_LAST_CELL;
}
return cell;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(cell.tag == SOME_TAG_OF_LAST_CELL)
{
// send call to server to fetch next page from server.
}
}

Using Images To Populate UITableView

I'm very new to iOS programming, and am trying to figure out something that is probably trivial. I'm trying to fetch Json data from Flickr, specifically just images, and use this data to populate pictures on a UITableView. This is my attempt:
- (void)jsonParsing
{
//-- Make URL request with server
NSHTTPURLResponse *response = nil;
NSString *jsonUrlString = [NSString stringWithFormat:#"http://api.flickr.com/services/feeds/photos_public.gne?tagmode=any&format=json&tags=QUERY"];
NSURL *url = [NSURL URLWithString:[jsonUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
//-- Get request and response though URL
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
//-- JSON Parsing
self.flickrArray = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:nil];
NSLog(#"Result = %#",self.flickrArray);
for (NSMutableDictionary *dic in self.flickrArray)
{
NSString *string = dic[#"media"];
if (string)
{
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
dic[#"media"] = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
}
else
{
NSLog(#"Error in url response");
}
}
}
- (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.
return [self.flickrArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSData *imageData = [self.flickrArray objectAtIndex:indexPath.row];
cell.image = [UIImage imageWithData:imageData];
return cell;
}
The only thing happening in the NSLog is : Result = (null). I can't for the life of me figure out what I'm doing incorrectly.

Again: Easy way to request JSON with posting data

I´m really new to Xcode and Objective-C ... I receive an JSON-Array to show the contents in my TableView:
in my -viewDidLoad:
[super viewDidLoad];
self.navigationItem.title = #"Kategorien";
NSURL *url = [NSURL URLWithString:#"http://www.visualstudio-teschl.at/apptest/kats.php"];
NSData *jsonData = [NSData dataWithContentsOfURL:url];
if(jsonData != nil)
{
NSError *error = nil;
_kategorien = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
}
and in my cellForRowAtIndexPath: method:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *data = [self.kategorien objectAtIndex:indexPath.row];
cell.textLabel.text = [data objectForKey:#"KAT_NAME"];
return cell;
It works great and shows my Strings (key -> KAT_NAME) in my Table.
But: How can i send a String with my request? For example i want to send "searchnumber = 2" with my request, like an ajax-request with javascript/jquery?
I searched but only could find examples that are to difficult (and maybe to oversized?) for my needs... is there no easy way like my request and ad something like "sendWithData" or is this method completely different with my simple request?
If you want to POST data, you'll need to create a NSMutableURLRequest object. You shouldn't use [NSData dataWithContentsOfURL:] anyway as this creates a synchronous request and blocks the UI. Even though it's a little more code, this is the right way to do it:
NSURL *url = [NSURL URLWithString:#"http://www.visualstudio-teschl.at/apptest/kats.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url];
request.HTTPMethod = #"POST";
request.HTTPBody = [#"searchnumber=2" dataUsingEncoding: NSASCIIStringEncoding];
[NSURLConnection sendAsynchronousRequest: request
queue: [NSOperationQueue mainQueue]
completionHandler:
^(NSURLResponse *r, NSData *data, NSError *error) {
// do something with data
}];

How do I loop through tweets to access geo information and add to an array

How would I loop through the JSON returned by a TWRequest to get the geo information of a tweet? I am using the code below - I have marked up the bit I am unsure about. the text component works fine, I'm just not sure how to create the array of geo data and access this...
- (void)fetchTweets
{
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
//NSLog(#"phrase carried over is %#", delegate.a);
// Do a simple search, using the Twitter API
TWRequest *request = [[TWRequest alloc] initWithURL:[NSURL URLWithString:
[NSString stringWithFormat:#"http://search.twitter.com/search.json?q=%#", delegate.a]]
parameters:nil requestMethod:TWRequestMethodGET];
// Notice this is a block, it is the handler to process the response
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if ([urlResponse statusCode] == 200)
{
// The response from Twitter is in JSON format
// Move the response into a dictionary and print
NSError *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
//NSLog(#"Twitter response: %#", dict);
NSArray *results = [dict objectForKey:#"results"];
//Loop through the results
for (NSDictionary *tweet in results) {
// Get the tweet
NSString *twittext = [tweet objectForKey:#"text"];
//added this one - need to check id NSString is ok??
NSString *twitlocation = [tweet objectForKey:#"geo"];
// Save the tweet to the twitterText array
[_twitterText addObject:twittext];
//this is the loop for the location
[twitterLocation addObject:twitlocation];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
else
NSLog(#"Twitter error, HTTP response: %i", [urlResponse statusCode]);
}];
}
"geo" is deprecated and probably not filled at all. I far as I remember it was deprecated in Twitter API v1.0 too. Try this code:
- (void)fetchTweets
{
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
//NSLog(#"phrase carried over is %#", delegate.a);
// Do a simple search, using the Twitter API
TWRequest *request = [[TWRequest alloc] initWithURL:[NSURL URLWithString:
[NSString stringWithFormat:#"http://search.twitter.com/search.json?q=%#", delegate.a]]
parameters:nil requestMethod:TWRequestMethodGET];
// Notice this is a block, it is the handler to process the response
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if ([urlResponse statusCode] == 200)
{
// The response from Twitter is in JSON format
// Move the response into a dictionary and print
NSError *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
//NSLog(#"Twitter response: %#", dict);
NSArray *results = [dict objectForKey:#"results"];
//Loop through the results
for (NSDictionary *tweet in results) {
// Get the tweet
NSString *twittext = [tweet objectForKey:#"text"];
//added this one - need to check id NSString is ok??
id jsonResult = [tweet valueForKeyPath:#"coordinates.coordinates"];
if ([NSNull null] != jsonResult) {
if (2 == [jsonResult count]) {
NSDecimalNumber* longitude = [jsonResult objectAtIndex:0];
NSDecimalNumber* latitude = [jsonResult objectAtIndex:1];
if (longitude && latitude) {
// here you have your coordinates do whatever you like
[twitterLocation addObject:[NSString stringWithFormat:#"%#,%#", latitude, longitude]];
}
else {
NSLog(#"Warning: bad coordinates: %#", jsonResult);
}
}
else {
NSLog(#"Warning: bad coordinates: %#", jsonResult);
}
}
// Save the tweet to the twitterText array
[_twitterText addObject:twittext];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
else
NSLog(#"Twitter error, HTTP response: %i", [urlResponse statusCode]);
}];
}

Fill up table view with UISearchDisplayController leads to EXC_BAD_ACESS! WHY?

I made some test with the UISearchDisplayController and I found some strange behavior I can not explain properly.
Please take a look at the following code:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return numOfRecords;
}
- (NSArray*) search:(NSString*)query {
// Prepare URL request to download statuses from Twitter
NSString *urlString = [NSString stringWithFormat:#"http://someaddress/search.ac?term=%#", query];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
// Perform request and get JSON back as a NSData object
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// Get JSON as a NSString from NSData response
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSArray *parsedResult = [json_string JSONValue];
return parsedResult;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellID = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
int i = [indexPath row];
if ( i >= [searchResult count] ) return cell;
NSString *res = [searchResult objectAtIndex:i];
[[cell textLabel] setText:res];
return cell;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
// WEB Request
NSArray *entries = [self search:searchString];
numOfRecords = [entries count];
NSMutableArray *entryTitles = [[NSMutableArray alloc] init];
for (int i=0; i<numOfRecords; i++) {
NSDictionary *entry = [entries objectAtIndex:i];
[entryTitles addObject:[entry objectForKey:#"title"]];
}
searchResult = entryTitles;
return YES;
}
The searchResult variable is a member variable of type NSArray. This code works fine, however if I change the assignment of searchResult to
searchResult = [NSArray arrayWithArray: entryTitles];
The program crashes after typing the second letter in the search field with a EXC_BAD_ACCESS.
Can somebody explain what is the problem that causes this error?
You probably just need to retain it:
searchResult = [[NSArray arrayWithArray: entryTitles] retain];
You need to do this because arrayWithArray just creates an autoreleased object that will be released in the near future. You need to add your retain to take ownership.
Once you've taken ownership, don't forget to release it somewhere.
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
// WEB Request
NSArray *entries = [self search:searchString];
[searchResult autorelease];
searchResult = [[entries valueForKeyPath:"#unionOfObjects.title"] retain];
return YES;
}
I ran across the same issue. My problem was that in cellForRowAtIndexPath I was releasing the object in the search results array after loading the string value into the cell for display.
Consequently, when I tried to search for anything it immediately crashed.
Check to make sure you aren't releasing the objects that you are searching against.