I'm programming a simple in-house economics app for our company, but I'm facing some problems. I populate a UITableView with information from dynamically generated objects like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
Payments *project = [appDelegate.projects objectAtIndex:indexPath.row];
if([project.parentProject isEqualToString:bottomTabBar.selectedItem.title]) {
NSLog(#"%# är lika med %# index: %d",project.parentProject, bottomTabBar.selectedItem.title, indexPath.row);
// Configure the cell...
NSMutableString *changeInValue = [[NSMutableString alloc] initWithFormat:#"%d",[[project.amountsek objectAtIndex:0] intValue]-[[project.amountsek objectAtIndex:1] intValue]];
if([changeInValue intValue] >= 0) {
[changeInValue insertString:#"+" atIndex:0];
cell.imageView.image = [UIImage imageNamed:#"up.png"];
} else {
cell.imageView.image = [UIImage imageNamed:#"down.png"];
}
NSMutableString *foreignCurrency = [[NSMutableString alloc] initWithString:#""];
if(![project.currency isEqualToString:#"SEK"]) {
[foreignCurrency appendFormat:#" - %#%d",project.currency,[[project.payments objectAtIndex:0] intValue]];
}
NSString *detailString = [[NSString alloc] initWithFormat:#"%#%d (%#)%#",#"SEK",[[project.amountsek objectAtIndex:0] intValue],changeInValue, foreignCurrency];
[changeInValue release];
[foreignCurrency release];
cell.textLabel.text = project.name;
cell.detailTextLabel.text = detailString;
[detailString release];
}
project = nil;
return cell;}
And everything works like a charm! However! When I press another tabButton I want it to reload the table and to display only the matched elements! (The matching works fine, the log prints out everything correctly) Although, the old table cells does not empty before the new ones are added.
Here's the code for the reload tabItem:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
NSLog(#"Tab clicked: %d", item.tag);
[sourcesTable reloadData];
}
How do I solve this?
I'm new to programming for the iPhone and I could really use some help.
Please call [sourcesTable reloadData]; in viewWillAppear method of that ViewController.m
This call every time when your view is appears.
Related
Sorry for posting this question again but I've looked into many answers and neither of them was helpfull to solve my issue.
So this my code :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"radioCell";
RadioTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[RadioTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
}
[self configureCommentCell:cell atIndexPath:indexPath];
return cell;
}
when I scroll down my cell get mixed up and some of data are repeated, so I've tried this :
static NSString *CellIdentifier = #"memberCell";
RadioCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[RadioTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
and this :
RadioTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil) {
cell = [[RadioTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil];
}
But it didn't fixed my issue and I get white empty cells ? please how to fix this issue ?
Update
- (void)configureCommentCell:(RadioTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
NSDictionary *object;
if ([_dataArray[indexPath.section] isKindOfClass:[NSArray class]])
object = [_dataArray[indexPath.section] objectAtIndex:indexPath.row];
else
object = [[_dataArray[indexPath.section] valueForKey:#"radioList"] objectAtIndex:indexPath.row];
if (object[#"jsonUrl"]) {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:object[#"jsonUrl"] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
//NSDictionary *tempObject = (NSDictionary *) responseObject;
if (![[responseObject objectForKey:#"type"] isEqualToString:#"error"]) {
NSDictionary *tempObject = [responseObject[#"data"] objectAtIndex:0];
cell.playingNow.text = tempObject[#"song"];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
cell.name.text = [NSString stringWithFormat:#" %#", object[#"title"]];
if (object[#"logoUrl"])
[cell.logo setImageWithURL:[NSURL URLWithString:object[#"logoUrl"]]];
}
I see that your problem is that you are fetching the data of you cells inside configureCommentCell that's called inside cellForRowAtIndexPath. which is wrong, because it too late to fetch data inside cellForRowAtIndexPath, in this delegate method you should return the cell.
this line may be called before retrieving the data from server :
cell.name.text = [NSString stringWithFormat:#" %#", object[#"title"]];
Instead you should:
Fetch the data inside a separate method for example fetchData
when the data is downloaded inside the completion block of AFNetworking method, store the data inside an NSArray called for example myDataArray still inside the completion block call [self.tableView reloadData];
In viewDidLoad method just call your method fetchData
And your cellForRowAtIndexPath should looks like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// hey please give me the cell to display ... harry up please
// please harry up ! oh my god you are fetching data from server
// while I am asking for the cell !
// ok I don't care do what you want
// I will return an empty cell anyway
// and guess what I will not take in consideration
// the retried data because it's inside a block
// which is called asynchronously
static NSString *cellIdentifier = #"radioCell";
RadioTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) {
cell = [[RadioTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier]; }
// now before return the cell you need to update the content of cell
// maybe you have an array of items and you should update the label
// for example here and then return the cell
cell.usernameLabel = self.myDataArray[indexPath.row]; // example
return cell;
}
Well the TableView is reusing the cells, and you add the image every time a cell is displaid. Thus when reusing the cell you add an other image, but there already is an image.
You will have to reuse the image view, and only add the image if you create the cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifer = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifer];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifer]autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(20,0,30,44)];
imageView.tag = 1001;
[cell addSubview:imageView];
[imageView release], imageView= nil;
}
TabBarTestAppDelegate *delegate = (TabBarTestAppDelegate *)[[UIApplication sharedApplication] delegate];
NSArray *local = delegate.myData;
// ok, it's horrible, don't look at it :-)
cell.textLabel.text = [NSString stringWithFormat:#"%#%#", #" " ,[local objectAtIndex:indexPath.row]];
//
NSString* name = nil;;
if (indexPath.row == 0) {
name = #"topicon";
}
else if (indexPath.row + 1 == [local count]) {
name = #"bottomicon";
}
else {
name = #"innericon";
}
UIImageView *imageView = (UIImageView *)[cell viewWithTag:1001];
imageView.image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:name ofType:#"png"]];
return cell;
}
I created an RSS reader that parses from a .xml file. I am trying to create a search bar and search display controller, but am not sure how to search the objectForKey "title" or objectForKey "summary" within the UITableView.
Any help would be greatly appreciated.
The numberOfRowsInSection and cellForRowAtIndexPath looked like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return self.parseResults.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//Check if cell is nil. If it is create a new instance of it
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure titleLabel
cell.textLabel.text = [[self.parseResults objectAtIndex:indexPath.row] objectForKey:#"title"];
cell.textLabel.numberOfLines = 2;
//Configure detailTitleLabel
cell.detailTextLabel.text = [[self.parseResults objectAtIndex:indexPath.row] objectForKey:#"summary"];
cell.detailTextLabel.numberOfLines = 2;
//Set accessoryType
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
//Set font and style
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
return cell;
}
I recently tried to follow this sample project - https://github.com/deepthit/TableViewSearch.git - based on a suggestion.
My code then looked like this:
#interface QldRecentJudgmentsViewController () {
__strong NSArray *mFilteredArray_;
__strong UISearchBar *mSearchBar_;
__strong UISearchDisplayController *mSearchDisplayController_;
}
#end
#implementation ViewController
#synthesize parseResults = _parseResults, HUD;
- (void)viewDidLoad {
[super viewDidLoad];
mSearchBar_ = [[UISearchBar alloc] initWithFrame:CGRectMake(0,
0,
self.view.bounds.size.width,
44)];
mSearchBar_.delegate = self;
mSearchBar_.placeholder = #"search";
self.tableView.tableHeaderView = mSearchBar_;
mSearchDisplayController_ = [[UISearchDisplayController alloc] initWithSearchBar:mSearchBar_
contentsController:self];
mSearchDisplayController_.searchResultsDelegate = self;
mSearchDisplayController_.searchResultsDataSource = self;
mSearchDisplayController_.delegate = self;
}
#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.parseResults.count;
if (tableView == self.searchDisplayController.searchResultsTableView ||
[mFilteredArray_ count] > 0)
{
return [mFilteredArray_ count];
}
return parseResults.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
id result;
if (tableView == self.searchDisplayController.searchResultsTableView ||
[mFilteredArray_ count] > 0)
{
result = [mFilteredArray_ objectAtIndex:indexPath.row];
}
else
{
result = [parseResults objectAtIndex:indexPath.row];
}
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//Check if cell is nil. If it is create a new instance of it
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Configure titleLabel
cell.textLabel.text = [[self.parseResults objectAtIndex:indexPath.row] objectForKey:#"title"];
cell.textLabel.numberOfLines = 2;
//Configure detailTitleLabel
cell.detailTextLabel.text = [[self.parseResults objectAtIndex:indexPath.row] objectForKey:#"summary"];
cell.detailTextLabel.numberOfLines = 2;
//Set accessoryType
//cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
//Set font and style
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *url = [[self.parseResults objectAtIndex:indexPath.row] objectForKey:#"link"];
NSString *title = [[self.parseResults objectAtIndex:indexPath.row] objectForKey:#"title"];
WebViewController *viewController = [[WebViewController alloc] initWithURL:url title:title];
[self.navigationController pushViewController:viewController animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - UISearchBarDelegate
- (void)searchBar:(UISearchBar *)searchBar
textDidChange:(NSString *)searchText {
if ([searchText length] == 0)
{
[self.tableView reloadData];
return;
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.title contains[cd] %# OR SELF.summary contains[cd] %#", searchText, searchText];
mFilteredArray_ = [self.parseResults filteredArrayUsingPredicate:predicate];
[self.tableView reloadData];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
mFilteredArray_ = nil;
[self.tableView reloadData];
}
However, when I follow this the RSS feed does not load anymore in the tableview, so there are no results. Nevertheless when I try to search it does not correctly search the "title" or "summary" and the search results do not appear correctly -the cells are not neatly aligned after searching for something and getting results. Also, the only way to see RSS in the tableview is to search for any generic string, but once you press cancel in the search bar the RSS feed disappears and shows an empty tableview.
Thanks for any help in advance.
I'm trying to insert data into the rows I've created, I will get all info in my Log but it only shows the last info in all of my rows. Could anyone suggest a way to avoid this error?
Please offer me some advice thanks!
You are never re-populating the cells, actually. You are creating the initial visible cells, and just reusing them with the same content.. please look below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath
{
static NSString *CellIdentifier = #"TestCell";
TestCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// HERE YOU ONLY WANT TO INSTANTIATE THE CELL
NSArray *topObjects = [[NSBundle mainBundle] loadNibNamed:#"TestCell" owner:nil options:nil];
for (id currentObject in topObjects)
{
if([currentObject isKindOfClass:[TestCell class]])
{
cell = (TestCell *) currentObject;
break;
}
}
}
// HERE YOU WOULD ACTUALLY POPULATE THE CELL WITH DATA
NSArray *array = [server get_texts:10 offset:0 sort_by:0 search_for:#""];
NSMutableString *s = [[NSMutableString alloc] init];
for (testMetaData *m in array){
[s appendFormat:#"%# %# \n", m.title,m.note];
cell.title.text = m.title;
NSLog(#" title %# ", m.title);
}
return cell;
}
Some info about UITableView:
So, a properly setup tableView only allocates and uses a limited number of UITableViewCells. After allocating, say 5 cells (this number is determined by "How many cells can you see at any given time?"), it will take an already created cell that has been scrolled out of the visible area, and gives it back to you in that method you are using, so you can re-populate it. So, cell variable will not be nil at that time, and your server code never gets called.
I think it has to do with your for loop.
NSMutableString *s = [[NSMutableString alloc] init];
for (testMetaData *m in array){
[s appendFormat:#"%# %# \n", m.title,m.note];
cell.title.text = m.title;
NSLog(#" title %# ", m.title);
}
Your cell.title.text = m.titlewill get the last m.title info at the end of the for loop.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath
{
//Load Cell for reuse
static NSString *CellIdentifier = #"TestCell";
TestCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell =[ [[NSBundle mainBundle] loadNibNamed:#"TestCell" owner:nil options:nil] lastObject];
}
//appending text and config cell
NSArray *array = [server get_texts:10 offset:0 sort_by:0 search_for:#""];
NSString *t = [array objectAtIndex:indexPath.row];
//Config cell - Not sure what you want. Maybe 10 different rows
cell.title.text = t;
return cell;
}
I have a very weird behavior with a UITableViewController in my project.
Normally it works perfectly but in one specific case it doesn't.
I have a dynamic table view with one custom type of cell. After filling all the data into the data source the table shows all the content correctly. There is a Pull-to-Refresh that updates the data source and table correctly. There are some filter buttons that update the only section with an animation correctly.
But if I click on one the detail view pushes into and if I go back click on one of these filter buttons again all the table view cells update except the ones I clicked. But if I click on this one again the detail view appears with the data of the cell that used to be there.
So the data updates just fine but the visible doesn't.
I would appreciate any suggestions. Thank you
P.S: Yes I do call the deselectRowAtIndexPath: method in the didSelectRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString *CellIdentifier = #"BANF";
BANFCell *cell = (BANFCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
if (cell == nil) {
cell = [[BANFCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// collect required data
Requisition *req;
// for right section
if ([self.tableView numberOfSections] == 1) {
req = [recent objectAtIndex:indexPath.row];
} else {
if (indexPath.section == 1) {
req = [recent objectAtIndex:indexPath.row];
} else {
req = [notSent objectAtIndex:indexPath.row];
}
}
NSMutableArray *shortTexts = [[NSMutableArray alloc] init];
// get description text and sort short texts ascending
// also the amount and currency
NSString *reqDescript;
NSString *amount;
NSString *currency;
for (Trait *trait in req.traits) {
if ([trait.name isEqualToString:#"DESCRIPTION"] && trait.value.length > 0) {
reqDescript = trait.value;
}
if ([trait.name isEqualToString:#"TOTAL_AMOUNT"] && trait.value.length > 0) {
amount = trait.value;
}
if ([trait.name isEqualToString:#"CURRENCY"] && trait.value.length > 0) {
currency = trait.value;
}
}
NSString *amountAndCurreny;
if (amount) {
NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[currencyFormatter setCurrencyCode:currency];
amountAndCurreny = [currencyFormatter stringFromNumber:[NSNumber numberWithDouble:amount.doubleValue]];
} else
amountAndCurreny = #"";
cell.amountLabel.text = amountAndCurreny;
NSArray *descriptors = [NSArray arrayWithObjects:[[NSSortDescriptor alloc] initWithKey:#"itm_number"
ascending:YES], nil];
NSArray *orderedArray = [req.positions sortedArrayUsingDescriptors:descriptors];
for (Position *position in orderedArray) {
for (Trait *trait in position.traits) {
if ([trait.name isEqualToString:#"SHORT_TEXT"] && trait.value.length > 0) {
[shortTexts addObject:trait.value];
}
}
}
UIImage *bgImage = [UIImage imageNamed:#"tableBG"];
cell.backgroundView = [[UIImageView alloc] initWithImage:bgImage];
// filling them in
if (req.iD.integerValue < 0) {
[cell.histLabel setText:NSLocalizedString(#"New", nil)];
} else {
[cell.histLabel setText:req.iD.stringValue];
}
[cell.datelabel setText:[labelDateFormatter stringFromDate:req.createDate]];
switch (req.status) {
case ReqStatusNew: [cell.imageView setImage:nil];
break;
case ReqStatusSaved: [cell.imageView setImage:[UIImage imageNamed:#"istGespeichertKiste.png"]];
break;
case ReqStatusApproved: [cell.imageView setImage:[UIImage imageNamed:#"genehmigtKiste.png"]];
break;
case ReqStatusInWFF: [cell.imageView setImage:[UIImage imageNamed:#"workflowKiste.png"]];
break;
case ReqStatusNotApproved: [cell.imageView setImage:[UIImage imageNamed:#"abgelehntKiste.png"]];
break;
case ReqStatusOrdered: [cell.imageView setImage:[UIImage imageNamed:#"istBestelltKiste.png"]];
break;
case ReqStatusDelivered: [cell.imageView setImage:[UIImage imageNamed:#"geliefertKiste.png"]];
break;
}
cell.shortTextLabel.marqueeType = MLContinuous;
cell.shortTextLabel.rate = 50;
cell.shortTextLabel.textAlignment = NSTextAlignmentLeft;
if (reqDescript == nil) {
cell.shortTextLabel.text = [shortTexts componentsJoinedByString:#", "];
} else if (shortTexts.count > 0) {
cell.shortTextLabel.text = [NSString stringWithFormat:#"%#: %#", reqDescript, [shortTexts componentsJoinedByString:#", "]];
} else {
cell.shortTextLabel.text = reqDescript;
}
[cell.shortTextLabel setFrame:CGRectMake(56, 35, 168, 18)];
return cell;
}
In viewWillAppear: I just set the buttons in the navigationcontroller and call
[tableview reloadData]
In viewDidLoad: just adding the delegate of the refresh control
The refresh control just calls [tableview reloadData] after updating the recent and notSent arrays from Core Data
A filter button just calls:
- (IBAction)filterPressed:(UIButton *)sender {
sender.selected = !sender.selected;
NSArray *filters = [dvFilterList componentsSeparatedByString:#","];
if ([[NSUserDefaults standardUserDefaults] boolForKey:[filters objectAtIndex:sender.tag]]){
[[NSUserDefaults standardUserDefaults] setBool:NO
forKey:[filters objectAtIndex:sender.tag]];
} else {
[[NSUserDefaults standardUserDefaults] setBool:YES
forKey:[filters objectAtIndex:sender.tag]];
}
[self updateTableViewData];
// only the section with the recent banfs
NSInteger section = [self numberOfSectionsInTableView:self.tableView] - 1;
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:section]
withRowAnimation:UITableViewRowAnimationFade];
}
(updateTableViewData is the method that just updates the recent and notSent arrays from Core Data)
You can try this ,
[tableView reloadData];
You can write this in cellForRowAtIndexPath
BANFCell *cell = (BANFCell *)[tableView dequeueReusableCellWithIdentifier:nil
forIndexPath:indexPath];
I finally found the solution by myself.
In my didSelectRowAtIndexPath: method I call performSegueWithIdentifier: and by giving the selected row as sender variable Xcode is somehow saving just the look of the cell in background that can only be deleted by removing the whole view controller from the stack.
Now I just give self as the sender because I don't need the variable.
So I code this:
[self performSegueWithIdentifier:#"goToReq" sender:self];
Instead of this:
[self performSegueWithIdentifier:#"goToReq" sender:[self tableView:tableView
cellForRowAtIndexPath:indexPath]];
I know this is not the answer for the original question, but might help someone else seeing similar problems.
I've encountered similar behavior with buggy code like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (condition)
{
CustomCell1* cell = [tableView dequeueReusableCellWithIdentifier:#"custom1" forIndexPath:indexPath];
// configure cell
// !! note how "return cell;" is missing !!
}
CustomCell2* cell = [tableView dequeueReusableCellWithIdentifier:#"custom2" forIndexPath:indexPath];
// configure cell
return cell;
}
Was fixed by actually returning the special-case cell from the conditional branch.
I have a UITableView which is populated with some parsed JSON twitter data. The intent is to have the user select the a row, and have the data passed to a modalViewController, which in this case is a map displaying coordinate and annotation information.
In the debug console I can see the data loaded into each visible UITableViewCell, plus the first one off screen (last loaded). When I run the app, and attempt to select a row, no matter which row I select, the data from the last loaded cell is always the data passed to the modalViewController.
I have logged to ensure the correct row is selected (it is) but no matter which row is selected, the last data loaded is always the data that is pushed.
First the Data Source Methods
#pragma mark -
#pragma mark UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSUInteger count = [self.results count];
return count > 0 ? count : 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ResultCellIdentifier = #"ResultCell";
static NSString *LoadCellIdentifier = #"LoadingCell";
NSUInteger count = [self.results count];
if ((count == 0) && (indexPath.row == 0)) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:LoadCellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:LoadCellIdentifier];
cell.textLabel.textAlignment = UITextAlignmentCenter;
}
if (self.connection) {
cell.textLabel.text = #"Loading...";
} else {
cell.textLabel.text = #"Not available";
}
return cell;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ResultCellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:ResultCellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.numberOfLines = 0;
cell.textLabel.font = [UIFont systemFontOfSize:14.0];;
}
UIImage *image = [UIImage imageNamed:#"medicaltag.png"];
cell.imageView.image = image;
// Begin UITableCell Data Formatting
NSDictionary *tweet = [self.results objectAtIndex:indexPath.row];
NSString* tweetText = [tweet objectForKey:#"text"];
if ([tweetText rangeOfString:#" *** "].location !=NSNotFound) {
NSArray *textItems = [tweetText componentsSeparatedByString:#" *** "];
NSLog(#"%#", textItems);
callAddress = [textItems objectAtIndex:0];
callAddress = [callAddress stringByReplacingOccurrencesOfString:#" , " withString:#", "];
callType = [textItems objectAtIndex:1];
NSLog(#"%#", callType);
NSLog(#"%#", callAddress);
NSString *latitude = [textItems objectAtIndex:2];
NSString *latStringPt1 = [[NSString alloc] init];
NSString *latStringPt2 = [[NSString alloc] init];
NSString *longitude = [textItems objectAtIndex:3];
longitude = [longitude stringByReplacingOccurrencesOfString:#"- " withString:#"-"];
NSString *lonStringPt1 = [[NSString alloc] init];
NSString *lonStringPt2 = [[NSString alloc] init];
int latStringLen = [latitude length];
int lonStringLen = [longitude length];
NSLog(#"The value of integer num is %i", latStringLen);
latStringPt1 = [latitude substringWithRange:NSMakeRange(0,latStringLen-6)];
latStringPt2 = [latitude substringFromIndex:latStringLen-6];
combinedLatString = [latStringPt1 stringByAppendingString:#"."];
combinedLatString = [combinedLatString stringByAppendingString:latStringPt2];
lonStringPt1 = [longitude substringWithRange:NSMakeRange(0,lonStringLen-6)];
lonStringPt2 = [longitude substringFromIndex:lonStringLen-6];
combinedLonString = [lonStringPt1 stringByAppendingString:#"."];
combinedLonString = [combinedLonString stringByAppendingString:lonStringPt2];
NSLog(#"%#", combinedLatString);
NSLog(#"%#", combinedLonString);
}
cell.textLabel.text = [NSString stringWithFormat:#"%#", callAddress];
cell.textLabel.font = [UIFont boldSystemFontOfSize:16];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", callType];
cell.detailTextLabel.font = [UIFont systemFontOfSize:14];
return cell;
}
Now the Delegate Method
#pragma mark -
#pragma mark Table View Delegate Methods*
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
NSLog(#"%i", row);
CallMapViewController *mapVC = [[CallMapViewController alloc] initWithNibName:#"CallMapViewController" bundle:[NSBundle mainBundle]];
mapVC.annotCallType = callType;
mapVC.annotCallAddress = callAddress;
NSLog(#"%#", mapVC.annotCallType);
NSLog(#"%#", mapVC.annotCallAddress);
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *lat = [f numberFromString:combinedLatString];
NSNumber *lon = [f numberFromString:combinedLonString];
mapVC.annotLatCoord = lat;
mapVC.annotLonCoord = lon;
NSLog(#"%#", lat);
NSLog(#"%#", lon);
NSLog(#"%#", callType);
NSLog(#"%#", callAddress);
[self presentModalViewController:mapVC animated:YES];
}
You already have your tweet data stored in your viewController's property results, so you just need to grab the data from there and parse it again (as Daryl Teo mentions) in didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString* tweetText = [[self.results objectAtIndex:indexPath.row] objectForKey:#"text"];
if ([tweetText rangeOfString:#" *** "].location != NSNotFound) {
NSArray *textItems = [tweetText componentsSeparatedByString:#" *** "];
CallMapViewController *mapVC = [[CallMapViewController alloc] initWithNibName:#"CallMapViewController" bundle:[NSBundle mainBundle]];
mapVC.callAddress = [[textItems objectAtIndex:0] stringByReplacingOccurrencesOfString:#" , " withString:#", "];
mapVC.callType = [textItems objectAtIndex:1];
[self presentModalViewController:mapVC animated:YES];
}
}
You get [indexPath row] but you don't use it.
And you've got "callType" and "callAddress" which aren't within the scope of the delegate method. They exist as instance variables of the viewController, and you set their values as you're creating the cells. That's why their values are always the values of the last cell.
You need to store the data in memory, so that you can reference it when you get the row from indexPath.
NSInteger row = [indexPath row];
NSString *tweetText = [tweetsStorageArray objectAtIndex: row];
/* Parse Tweet Text again */
You can either store tweets as text, or create a storage class and store that.
From what I can see in the method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
You take the [indexPath row]; but you don't chose your data base on that.
I see that in your delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath () you are only accessing the selected row variable for NSLog messages.
You would probably need to access the cell using UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath] and its contents using callType = cell.detailTextLabel.text;and callAddress = cell.textLabel.text;