I have been struggling with something for weeks and it has brought a real halt to my progress. I have asked a question a few times on SO, people have been helpful but no-one has cracked what I am doing wrong. It seems a fairly simple thing so hopefully someone out there will have a lightbulb moment and solve this. I am implementing a TWRequest, the result is coming back in a dictionary, I am looping through the results to extract a part of the tweet and creating an array of these 'text' components. Straight adter the loop through I am peinting the log of the array - _twitterText and it prints fine. Staright after this method is complete it seems as though _twitterText is being dumped. I have created it in my .h file as a strong property and created an ivar in viewdidload. Still no joy. how do I retain this array to use in another Method? Here is my .h file....
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import "CustomCell.h"
#import "AppDelegate.h"
#import <Twitter/Twitter.h>
@interface MyViewController : UITableViewController <CLLocationManagerDelegate>
{
CLLocationManager *here;
}
@property(strong) NSDictionary *dict;
@property(strong) CLLocationManager *here;
@property (strong, nonatomic) NSMutableArray *twitterText;
- (void)fetchTweets;
@end </p>
Here is my .m implementation file......
#import "MyViewController.h"
@interface MyViewController ()
@end
@implementation MyViewController
@synthesize dict;
@synthesize twitterText = _twitterText;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_twitterText = [[NSMutableArray alloc] init];
here = [[CLLocationManager alloc] init];
here.delegate = self;
[here startUpdatingLocation];
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
NSLog(@"phrase carried over is %@", delegate.a);
[self fetchTweets];
}
- (void)fetchTweets
{
TWRequest *request = [[TWRequest alloc] initWithURL:[NSURL URLWithString:
@"http://search.twitter.com/search.json?q=%40wimbledon"]
parameters:nil requestMethod:TWRequestMethodGET];
[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"];
// Save the tweet to the twitterText array
[_twitterText addObject:twittext];
}
NSLog(@"MY ************************TWITTERTEXT************** %@", _twitterText);
}
else
NSLog(@"Twitter error, HTTP response: %i", [urlResponse statusCode]);
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"MyCell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
//cell.venueDetails.text = [_twitterText objectAtIndex:indexPath.row];
NSLog(@"MY ************************OTHER BIT THAT WONT PRINT************** %@", _twitterText);
return cell;
}
So the issue here is that your completion handler that you pass to -[TWTweet performRequestWithHandler:]
isn't going to (can't) fire until the network connection is complete and the server responds to your request. That could take hundreds of milliseconds or even seconds to complete. (Or it may never happen).
Meanwhile while that is happening, the UITableView wants to draw itself and so will ask you how many sections/rows you have and then will ask you for a cell for each row. So when the table view asks, you should return the actual number of rows you have to draw at that time:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.twitterText count]; // the actual number of rows we have right now
}
So then the next step you need is to reload the table when your data is actually in from the server. That will prompt your table view to ask again for the number of sections and rows, and then ask for cells for each section and row. So somewhere in your completion block after you've processed all your data you will need to do this:
dispatch_async(dispatch_get_main_queue(), ^{
// you'll need an outlet to the UITableView
// here I assume you call that 'tableView'
// then just ask it to reload on the main thread
[self.tableView reloadData];
});
I hope that helps?