EDIT: By "function" I am referring to the (UITableView)tableView cellForRowAtIndexPath, it's stated in my title but I wanted to make it clear
So, yes, there are other answers I have a couple 1stexample, 2ndexample . My function is not being called for some reason. I was following this tutorial. Went back 5 different times to make sure I did all the datasource and delegates right, I think I am. I have done iOS apps before and never had an issue with this. I don't think anything is wrong with the code, I debugged it and it should be working fine. I'll post it anyways just in case I am making an amateur mistake somewhere in there. Don't think I am, but I've been wrong before.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
ViewController.m
#interface ViewController ()
#property (strong, nonatomic) NSArray *array;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self twitterTimeline];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark Table View Data Source Methods
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
NSDictionary *tweet = _array[indexPath.row];
cell.textLabel.text = tweet[#"text"];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
-(void)twitterTimeline
{
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[account requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error){
if(granted == YES)
{
NSArray *arrayOfAccounts = [account accountsWithAccountType:accountType];
if([arrayOfAccounts count] > 0) {
ACAccount *twitterAccount = [arrayOfAccounts lastObject]; //grabs last account that is on iPhone, perhaps we would have the user make a selection of which user but for this beginning its fine
NSURL *requestAPI = [NSURL URLWithString:#"http://api.tiwtter.com/1.1/statuses/user_timeline.json"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
[parameters setObject:#"100"
forKey:#"count"];
[parameters setObject:#"1" forKey:#"include_entities"];
SLRequest *posts = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:requestAPI parameters:parameters];
posts.account = twitterAccount;
[posts performRequestWithHandler:^(NSData *response, NSHTTPURLResponse *urlResponse, NSError *error) {
self.array = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];
if(self.array.count != 0) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
}];
}
} else {
NSLog(#"%#", [error localizedDescription]);
}
}];
}
#end
Here's my referencing outlets (which is why I think it's really weird it's not calling the function). ScreenshotLink. Sorry I guess I need 10 rep to post pictures directly on SO.
I very much appreciate any help given.
Why don't you put a breakpoint on [self.tableView reloadData];. If your breakpoint never gets hit then your array is empty. You should also check the error value if it has anything useful in it.
I would put a NSLog in the
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"array count is %d", [_array count]);
return [_array count];
}
I think it's empty and will therefore not call the other methods.
Related
I am aware this question has been asked previously, but the answers provided have not solved my issue.
For instance, I have a very simple array of objects outlined in viewDidLoad:
#implementation MyViewController {
NSArray *tableData;
}
- (void)viewDidLoad
{
[super viewDidLoad];
tableData = [NSArray arrayWithObjects:#"Hello", #"My", #"Name", #"Is"];
NSLog(#"My Data: %#", tableData);
which is called in a tableView using cellForRowAtIndexPath
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
This works fine and the NSLog shows my array. However, when i outline tableData outside of viewDidLoad, my array is (null).
My question is, how do I make my array available for the tableView when it is specified outside of ViewDidLoad?
edit: Here is my specific code:
#import <UIKit/UIKit.h>
#import "PhotoView.h"
#interface FrontViewController : UIViewController
#property (nonatomic, retain) UITableView *tableView;
#end
#import "FrontViewController.h"
#import "StreamScreen.h"
#import "API.h"
#import "PhotoView.h"
#import "StreamPhotoScreen.h"
#import "PrivateViewController.h"
#import "SWRevealViewController.h"
#import "PhotoScreen.h"
#import "RearViewController.h"
#import "SimpleTableCell.h"
#interface FrontViewController()
// Private Methods:
- (IBAction)pushExample:(id)sender;
#end
#implementation FrontViewController{
NSArray *tableData;
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(#"Front View", nil);
SWRevealViewController *revealController = [self revealViewController];
[self.navigationController.navigationBar addGestureRecognizer:revealController.panGestureRecognizer];
UIBarButtonItem *revealButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"reveal-icon.png"]
style:UIBarButtonItemStyleBordered target:revealController action:#selector(revealToggle:)];
self.navigationItem.leftBarButtonItem = revealButtonItem;
// This works if I uncomment
//tableData = [NSArray arrayWithObjects:#"Hello", #"My", #"Name", #"Is", nil];
[self refreshStream];
}
-(void)refreshStream {
// call the "stream" command from the web API
[[API sharedInstance] commandWithParams:
[NSMutableDictionary dictionaryWithObjectsAndKeys:#"stream", #"command", nil]
onCompletion:^(NSDictionary *json) {
//got stream
[self showStream:[json objectForKey:#"result"]];
NSMutableArray *myData = [[NSMutableArray alloc] init];
myData = [json objectForKey:#"result"];
NSArray *userNameData = [myData valueForKey:#"username"];
[self loadData];
tableData = userNameData;
[self.tableView reloadData];
// I can see my json array in NSLog
NSLog(#"here's the results: %#", tableData);
}];
}
//This doesn't work either
//-(void)loadData {
// Add the data to your array.
//tableData = [NSArray arrayWithObjects:#"Hello", #"My", #"Name", #"Is", nil];
//NSLog(#"My Data: %#", tableData);
// Now load the table view.
// [self.tableView reloadData];
//}
-(void)showStream:(NSArray*)stream {
for (int i=0;i<[stream count];i++) {
NSDictionary* photo = [stream objectAtIndex:i];
}
NSArray *checkData = [stream valueForKey:#"username"];
//I can see my data in NSLog
NSLog(#"here's the results: %#", checkData);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 78;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
cell.thumbnailImageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
cell.prepTimeLabel.text = [prepTime objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"didSelectRowAtIndexPath");
/*UIAlertView *messageAlert = [[UIAlertView alloc]
initWithTitle:#"Row Selected" message:#"You've selected a row" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];*/
UIAlertView *messageAlert = [[UIAlertView alloc]
initWithTitle:#"Row Selected" message:[tableData objectAtIndex:indexPath.row] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
// Display the Hello World Message
[messageAlert show];
// Checked the selected row
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"willSelectRowAtIndexPath");
if (indexPath.row == 0) {
return nil;
}
return indexPath;
}
#end
-(void)refreshStream {
// call the "stream" command from the web API
[[API sharedInstance] commandWithParams:
[NSMutableDictionary dictionaryWithObjectsAndKeys:#"stream", #"command", nil]
onCompletion:^(NSDictionary *json) {
//got stream
[self showStream:[json objectForKey:#"result"]];
NSMutableArray *myData = [json objectForKey:#"result"];
NSArray *userNameData = [myData valueForKey:#"username"];
}];
tableData = userNameData;
[self.tableView reloadData];
}
You're falling into a very common trap with asynchronous programming here.
commandWithParams takes a completion block, which is where you are getting the data out of the JSON. This block is not executed until the API call has returned. The sequence of events that happens when you run this code is:
commandWithParams is called
tableData is assigned to the contents of userNameData (which presumably you've also declared somewhere else otherwise this would not even compile)
reloadData is called
.... time passes
The completion block is executed and the JSON is read out into local variables, which are then instantly destroyed.
You need to move the two lines (points 2 and 3 in the list above) inside the completion block. There will be no data for your table until the block returns.
Ok my understanding of your question is that you want to assign variables to your NSArray in another method (not viewDidLoad) and then load the table view.
This is simple, just make a method which is in charge of adding the data to your array and then reload your table view like so:
-(void)viewDidLoad {
[super viewDidLoad];
// Call your method.
[self loadData];
}
-(void)loadData {
// Add the data to your array.
tableData = [NSArray arrayWithObjects:#"Hello", #"My", #"Name", #"Is"];
NSLog(#"My Data: %#", tableData);
// Now load the table view.
[myTableView reloadData];
}
Update 1
It would be much more helpful if you could share your code with us. How your and setting up your tableview, when its being called/etc....
Update 2
Ok well it seems obvious what yoru issue is. Your table view will never load like that. You need to call the tableview reloadData method outside the cellForRowAtIndexPath method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)[self.tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
cell.thumbnailImageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
cell.prepTimeLabel.text = [prepTime objectAtIndex:indexPath.row];
return cell;
}
So the method call [self.tableView reloadData]; should only be called in your refreshStream method.
Update 3
You need to initialize your NSMutableArray before you can add data to it. initialize it in your refreshStrem method like so:
-(void)refreshStream {
// call the "stream" command from the web API
[[API sharedInstance] commandWithParams:[NSMutableDictionary dictionaryWithObjectsAndKeys:#"stream", #"command", nil] onCompletion:^(NSDictionary *json) {
//got stream
[self showStream:[json objectForKey:#"result"]];
NSMutableArray *myData = [[NSMutableArray alloc] init];
myData = [json objectForKey:#"result"];
NSArray *userNameData = [myData valueForKey:#"username"];
}];
tableData = userNameData;
[self.tableView reloadData];
}
Update 4
Ok well after reading #jrturton answer, I think its safe to assume that my answer is rubbish. To anyone reading my answer, please view #jrturton post.
Well I feel pretty sheepish. The answer was simple. I was so hung up on Json and API that all I didn't check the basics. All I need was in my .h file:
#property (strong, nonatomic) IBOutlet UITableView *tableView;
I had originally had:
#property (nonatomic, retain) UITableView *tableView;
I created an api using kimono and here is my code.
#import "PlayerRankingsTableViewController.h"
#import "RankingsTableViewCell.h"
#define kBgQueue dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define kPlayerRankingsURL [NSURL URLWithString:#"https://www.kimonolabs.com/api/bg6tcuuq?apikey=xgp4nU6xA9UcBWSe0MIHcBVbAWz5v4wR"]
#interface PlayerRankingsTableViewController () {
}
#property (nonatomic, strong) NSArray *playerRankings;
#end
#implementation PlayerRankingsTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(kBgQueue, ^{
NSData *data = [NSData dataWithContentsOfURL:
kPlayerRankingsURL];
[self performSelectorOnMainThread: #selector(initializePlayerRankingsArray:)
withObject:data waitUntilDone:YES];
});
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be rexrcreated.
}
- (NSArray *)initializePlayerRankingsArray:(NSData *)responseData {
NSError* error;
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSArray *myPlayerRankings = [[json objectForKey:#"results"]objectForKey:#"collection1"];
self.playerRankings = myPlayerRankings;
NSLog(#"%#", self.playerRankings);
return self.playerRankings;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.playerRankings count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RankingsTableViewCell *cell = (RankingsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = (RankingsTableViewCell *)[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
NSDictionary *rankings = [self.playerRankings objectAtIndex: indexPath.row];
NSString *rank = [rankings objectForKey:#"rank"];
NSString *name = [rankings objectForKey:#"name"];
NSString *points = [rankings objectForKey:#"points"];
[cell.playerRank setText:rank];
cell.playerName.text = name;
cell.playerPoints.text = points;
return cell;
}
#end
I think there is nothing wrong with data parsing process, because the console displays my data parsed from the web correctly.
However, when I ran the app, I saw nothing but a empty table.
Again, I think this might be something simple and new to programming.
Thank you in advance, and sorry for being such a burden.
In initializePlayerRankingsArray: you shouldn't be returning the array because nothing it there to receive it. You have already set self.playerRankings, so that is enough.
What is missing from this method is [self.tableView reloadData]; (which should be the last line after self.playerRankings is set).
I am currently trying to load a plist file from a URL. I'm not sure if the way I have my code set up is causing it to crash or if I'm doing something wrong.
.m file
#import "deptTableViewController.h"
#interface deptTableViewController ()
#property (nonatomic, copy) NSDictionary *names;
#property (nonatomic, copy) NSArray *keys;
#property (nonatomic, strong) NSMutableArray *filterednames;
#property (nonatomic, strong) UISearchDisplayController *searchController;
#end
#implementation deptTableViewController
#synthesize names, keys, filterednames, searchController, searchNames;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UITableView *tableview = (id) [self.view viewWithTag:1];
[tableview registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
filterednames = [[NSMutableArray alloc]init];
searchController = [[UISearchDisplayController alloc]init];
searchController.searchResultsDataSource = self;
// This will get the plist into data format
NSData *dataReturn = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:#"http://morphinggamers.ca/staff.plist"]];
NSString *path = [[NSBundle mainBundle]pathForResource:#"staff" ofType:#"plist"];
names = [NSDictionary dictionaryWithContentsOfFile:path];
keys = [[names allKeys]sortedArrayUsingSelector:#selector(compare:)];
keys = [NSKeyedUnarchiver unarchiveObjectWithData:dataReturn];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (tableView.tag == 1) {
return [keys count];
}
else{
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (tableView.tag == 1) {
NSString *key = keys[section];
NSArray *keyValues = names[key];
return [keyValues count];
}
else {
return [filterednames count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
if (tableView.tag == 1) {
names = keys[indexPath.row];
NSString *teacherNames = names[#"teacherNames"];
cell.textLabel.text = teacherNames;
}
else{
cell.textLabel.text = filterednames [indexPath.row];
}
return cell;
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
if (tableView.tag == 1) {
return keys[section];
}
else{
return nil;
}
}
#pragma mark - Search Display And Delegate Methods
-(void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView {
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{
[filterednames removeAllObjects];
if (searchString.length > 0) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains [search] %#", self.searchNames.text];
for (NSString *key in keys) {
NSArray *matches = [names[key]filteredArrayUsingPredicate:predicate];
[filterednames addObjectsFromArray:matches];
}
}
return YES;
}
#end
You can only use initwithcontentsofurl using local files (files on your device already) This URL is on a server so you need to use a network request to fetch the data from the server.
NSURLRequest *request = [NSURLRequest requestWithURL:#"http://morphinggamers.ca/staff.plist"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSDictionary *names = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:0 format:0 errorDescription:nil];
keys = [[names allKeys]sortedArrayUsingSelector:#selector(compare:)];
keys = [NSKeyedUnarchiver unarchiveObjectWithData:dataReturn];
//might want to reload the tableview
[self.tableview reloadData]
}];
I am currently trying to display a NSMutableArray into a UITableView. The problem lies in the NumberOfRowsInSection and in the CellForRowAtIndex. I am able to fetch twitter feed and logic to the console, but I can't seem to display it to my UITable view. What could be the reason?
#import "ViewController.h"
#import <Accounts/Accounts.h>
#import <Social/Social.h>
#import "TwitterPostInfo.h"
#import "CustomCell.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
twitterPosts = [[NSMutableArray alloc]init];
[self refreshTwitter];
[super viewDidLoad];
// 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)refreshTwitter
{
ACAccountStore *accountStore = [[ACAccountStore alloc]init];
if (accountStore != nil)
{
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
if (accountType != nil)
{
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if (granted)
{
//Succesful Access
NSArray *twitterAccounts = [accountStore accountsWithAccountType:accountType];
if (twitterAccounts != nil)
{
ACAccount *currentAccount = [twitterAccounts objectAtIndex:0];
if (currentAccount != nil)
{
NSString *requestString = #"https://api.twitter.com/1.1/statuses/user_timeline.json";
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:[NSURL URLWithString:requestString] parameters:nil];
[request setAccount:currentAccount];
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if ((error == nil) && ([urlResponse statusCode] == 200))
{
NSArray *twitterFeed = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
// loop throught all posts
for (NSInteger i=0; i<[twitterFeed count]; i++)
{
TwitterPostInfo *postInfo = [self createPostInfoFromDictionary:[twitterFeed objectAtIndex:i]];
if (postInfo != nil)
{
[twitterPosts addObject:postInfo];
}
}
}
}];
}
}
}
else
{
//Access Denied
}
}];
}
}
}
-(TwitterPostInfo*)createPostInfoFromDictionary:(NSDictionary*)postDictionary
{
NSString *timeDateString = [postDictionary valueForKey:#"created_at"];
NSDictionary *userDictionary = [postDictionary objectForKey:#"user"];
NSString *userString = [userDictionary valueForKey:#"screen_name"];
NSString *userDesc = [userDictionary valueForKey:#"description"];
NSString *tweetText = [postDictionary valueForKey:#"text"];
TwitterPostInfo *postInfo = [[TwitterPostInfo alloc]initWithPostInfo:userString userDesc:userDesc text:tweetText timeDateInfo:timeDateString];
return postInfo;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [twitterPosts count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CloneCell"];
if (cell != nil)
{
// ISSUE BEGINS HERE
//TwitterPostInfo *postInfo = (TwitterPostInfo*) twitterPosts[indexPath.row];
//cell = [twitterPosts objectAtIndex:indexPath.row];
cell.textLabel.text = [twitterPosts objectAtIndex:indexPath.row];
}
return cell;
}
#end
The post about the valid cell object is important, but your real problem here is that you are assigning an object of type TwitterPostInfo to cell.textLabel.text, which is an NSString.
If what you're trying to display is the text of the Tweet, you'll want something more like this:
TwitterPostInfo *postInfo = (TwitterPostInfo*) twitterPosts[indexPath.row];
cell.textLabel.text = postInfo.text; //or however your getter for the text is implemented
If you're trying to display all of the information of the Tweet in the cell, you're going to have to create your own custom cell and then assign each UILabel in the cell to the different properties stored in the TwitterPostInfo object.
dequeueReusableCellWithIdentifier: may return nil. In this case, you need to create a proper UITableViewCell yourself.
Try creating a cell if it is nil. Always make sure to return a valid cell object.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CloneCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] init];
}
cell.textLabel.text = [twitterPosts objectAtIndex:indexPath.row];
return cell;
I am very new at Objective C and Xcode but I am learning a little bit every day!:)
I am trying to build an application that will show a webb api in my tableview, but it does not show.. when I NSLog it, it shows that my search worked and that it got the data i was looking for but it will not show in my tableView unfortunately..
If someone as time to look at the code and try to figure out what is wrong that would be great, or if someone hade a similar problem, just throw it out there so i can check if i did the same thing:)
Best regards. Filip
(Sorry for my bad english, I`m from Sweden and in a hurry..)
- my .m file
#import "FoodTableViewController.h"
#interface FoodTableViewController ()
#property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
#property(nonatomic)NSMutableArray *foodNames;
#end
#implementation FoodTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.foodNames = [#[]mutableCopy];
self.searchBar.delegate = self;
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchbar
{
NSString *urlString = [NSString stringWithFormat:#"http://matapi.se/foodstuff?query=%#",self.searchBar.text];
NSURL *URL = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSError *parseError;
NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError];
dispatch_async(dispatch_get_main_queue(),^{
for(int i=0;i<json.count;i++){
NSString *foodName = json[i][#"name"];
[self.foodNames addObject:foodName];
NSLog(#"Added: %#",foodName);
NSLog(#"FOODLIST LENGTH: %d",self.foodNames.count);
}
});
}];
[task resume];
[self.tableView reloadData];
}
#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.
return self.foodNames.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if(self.foodNames[indexPath.row]){
NSLog(#"Cell text %#",self.foodNames[indexPath.row]);
cell.textLabel.text = self.foodNames[indexPath.row];
}else{
cell.textLabel.text = #"Loading..";
}
return cell;
}
#end
- my .h file
#import <UIKit/UIKit.h>
#interface FoodTableViewController : UITableViewController<UISearchBarDelegate>
#end
dataTaskWithRequest:... is an asynchronous method, which means that the results are not available at the time of your reloadData call. You'll need to add that call after all your data is added to the array. In part...
for(int i=0;i<json.count;i++){
NSString *foodName = json[i][#"name"];
[self.foodNames addObject:foodName];
NSLog(#"Added: %#",foodName);
NSLog(#"FOODLIST LENGTH: %d",self.foodNames.count);
}
[self.tableView reloadData];