dequeueReusableCellWithIdentifier forIndexPath - iphone

I have a custom/sub-classed UITableViewCell using NSLayoutConstraints. The left most UIImageView may or may not be populated with an image, and if not, the objects to right of this field will naturally shift to the left. Works well within the custom UITableViewCell, however I'll be populating the content with my custom UITableViewController. Unfortunately, following code will populate every row cell.dispatchedView with an image -- though I've trapped to not populate rows with anything.
This has something to do with the dequeueReusableCellWithIdentifier. Ideas?
static NSString *CellIdentifier = #"CellIdentifier";
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[NXGActiveUnitsCell class] forCellReuseIdentifier:CellIdentifier];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
NSDictionary *item = [self.model.dataSource objectAtIndex:indexPath.row];
NXGActiveUnitsCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if([[[item objectForKey:#"cfs_no"] clean] length] > 0) {
cell.dispatchedView.image = [UIImage imageNamed:#"p.png"];
NSLog(#">>>%#",[item objectForKey:#"cfs_no"] );
} else {
NSLog(#">>> i got nothing so I should not touch this row...");
}
cell.departmentIconView.image = [UIImage imageNamed:#"f.png"];
cell.unitLabel.text = [item valueForKey:#"unit_id"];
return cell;
}

I don't know if this already solves your problem, but you should
definitely set
cell.dispatchedView.image = nil;
in the else-case, because cells are reused.

Related

iOS - UITableView Changing Datasourse

I was wondering if anyone knows how to solve this problem:
I have a UITableview, where the datasource can continue to grow. The issue is when I add elements to the data source, the table cells get messed up.
Each table cell has a text field where the user can enter data into it, but whenever I add data to the datasource the comments replicate to other cells.
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"ImageTableCell";
ImageTableCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
Picture *aPicture = (Picture *) [self.imageData objectAtIndex:[indexPath row]];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ImageTableCell" owner:self options:NULL];
cell = (ImageTableCell *)[nib objectAtIndex:0];
}
NSLog(#"comment %# index %d", aPicture.comment, [indexPath row]);
cell.cellImage.image = aPicture.picture;
cell.commentField.delegate = self;
cell.commentField.text = aPicture.comment;
cell.index = [indexPath row];
cell.tag = [indexPath row];
return cell;
}
self.imagedata is a NSMutabaleArray.
EDIT
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.imageData count];
}
-(void) reloadImages:(NSNotification *) aNotification {
self.imageData = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).currentUserData.images;
[self.imageTableView reloadData];
}
a screenshot http://www.mikerizzello.com/pic.png
Thanks
EDIT:
I think you might have a bad MVC pattern. Here's what I would do:
Take your custom cell, ImageViewCell, and make that class your textField delegate. Add a property for your custom Picture object, and set that in cellForRow...
Then, in your textFieldDelegate methods inside the custom cell class, you can change set the contents of your PictureObject there. I have a feeling that you're handling text input in the viewController, and the index of the data object in your array is getting mixed up and you're applying the comment field text to the wrong item in the array.
EDIT
I think it has something to do with cell reuse. The contents of your cell are not getting wiped out upon reusing a cell.
Try this block before you return the cell:
if (!aPicture.comment) {
cell.commentField.text = #"";
} else {
cell.commentField.text = aPicture.comment;
}
Have you try with
if (cell == nil) {
cell = (ImageTableCell*)[[ImageTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
Anyway you can also set different reuseIdentifier for each of cells but it will be bad idea, I would like to help you but i think need to run this project.
Please let me know if code above give better solution.

iPhone sdk UITableView cell reuse identifier

I am using UITableView. When a book is downloaded i am adding a checkmark image to my table. And i have done this. But when am scrolling my table am getting the image even for non-downloaded books (i.e) my table cell are reused. For this i googled and checked my code with that. Everything seems to be the same. Here is my code,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIImage *cellImage= [cacheImage getCachedImage:[listOfThumImages objectAtIndex:indexPath.row]];
if(cellImage == nil)
{
DeviantDownload *download;
download = [DownloadsArray objectAtIndex:indexPath.row];
cellImage = download.image;
if (cellImage == nil)
{
download.delegate = self;
}
NSLog(#"cellImage%#",cellImage);
UIImageView *imgView;
static NSString *CellIdentifier = #"";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
imgView1 = [[UIImageView alloc] initWithFrame:CGRectMake(680, 60, 40, 40)];//self.view.bounds.size.width-
[imgView1 setImage:[UIImage imageNamed:#"Downloaded.png"]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults objectForKey:#"firstRun"])
{
if([[[appDelegate selectDB] valueForKey:#"bookname"] containsObject:[listOfBooks objectAtIndex:indexPath.row]] )
{
NSString *cellValue = [listOfBooks objectAtIndex:indexPath.row];
cell.contentView addSubview:imgView1];
}
return cell;
}
}
}
What's wrong with my code? Kindly help me out. Thanking You.
If you want that a cell does not display the image then simply remove the imageview, for that cell. set a view.tag for the image view, and retrieve it, then remove it.
What you are doing now, is to add a image sub view as soon as you need it for a cell, and later reuse that cell for all other rows. But you never removed the imageview for cells that dont need it.
CheckMarks with UITableView is little complicated then what it seems. First of all you'll have to save the status of your row which already has the bookmark. And, compare it in your cellForRowAtIndexPath method. What you can do is create on NSMutableArray. Save 1 for downloaded book and 0 for non-downloaded book. In your cellForRowAtIndexPath method compare [array objectAtIndex:indexpath.row] and set the image accordingly.
Also, change :
static NSString *CellIdentifier = #"";
To :
static NSString *CellIdentifier = #"MyCell";

How can i use prototype cell in storyboard with search result controller

I have tableview with search result controller when search in search bar get this error indicate that there is no cell and get the below error .How can create my prototype cell in this method CellForRowAtIndexPath
Code :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"HoCell";
Ho *cell;
Ho *item;
if (tableView == self.searchDisplayController.searchResultsTableView) {
if (cell == nil)
{
cell = [[Ho alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"HoCell"];
}
item = [searchResultsController objectAtIndexPath:indexPath];
}
else{
cell = (Ho*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
item = [fetchedResultsController objectAtIndexPath:indexPath];
}
cell.ho.text = item.name;
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"se.png"]];
return cell;
}
Error :
*** Assertion failure in -[UISearchResultsTableView _configureCellForDisplay:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:5471
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
There may be two possibilities Here :
1) You are returning a number larger than your Array Count from
tableView:numberOfRowsInSection:. Don't.
2) One or more of your cell# outlets is not hooked up in your nib, or
is not hooked up to a UITableViewCell (or subclass). Hook them up
properly.
Go through this Ray Wenderlich's Link :
How to Add Search Into a Table View
Check this SO Questions :
1) UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath: Exception
2) ios 5 UISearchDisplayController crash
One More Beautiful Link : Custom Prototype Table Cells and Storyboards Just see this Portion :
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:UYLCountryCellIdentifier];
if (cell == nil)
{
[self.countryCellNib instantiateWithOwner:self options:nil];
cell = self.countryCell;
self.countryCell = nil;
}
// Code omitted to configure the cell...
return cell;
}
Your code seems to be buggy. You check for cell == nil while it is not set to nil initially. It also looks a bit strange that you allocate your cells in that way based on search mode.
Anyways, I would do it different way. Imho the way I do it is almost canonical :) Just use your search result to populate your cells with correct data for each case (search mode and normal mode). In this example, searchResult and dataSource are arrays with strings. I think in real life for you it will be something more complex like array of nsdictionary.
In your view controller:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)_section
{
/* Use correct data array so that in search mode we draw cells correctly. */
NSMutableArray *data = searching ? searchResult : dataSource;
return [data count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/* Use correct data array so that in search mode we draw cells correctly. */
NSMutableArray *data = searching ? searchResult : dataSource;
static NSString *CellIdentifier = #"CellId";
CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomTableViewCell alloc] initWithIdentifier:CellIdentifier] autorelease];
}
/* Note this is only correct for the case that you have one section */
NSString *text = [data objectAtIndex:[indexPath row]]
cell.textLabel.text = text;
/* More setup for the cell. */
return text;
}
And here are delegate methods for search controller and some helpers:
- (void) searchTableView
{
NSString *searchText = searchBar.text;
for (NSString *item in dataSource) {
NSRange range = [item rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (range.length > 0) {
[searchResult addObject:item];
}
}
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
searching = NO;
}
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
{
searching = NO;
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0]
withRowAnimation:UITableViewRowAnimationAutomatic];
[searchResult removeAllObjects];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchText
{
[searchResult removeAllObjects];
if ([searchText length] > 0) {
searching = YES;
[self searchTableView];
} else {
searching = NO;
}
return YES;
}
Hope this helps.
I have the same issue, here is what is did and it is now working perfectly..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Here is my code BEFORE
//
OPUsersTableViewCell *tableCell = [tableView dequeueReusableCellWithIdentifier:TableCellID];
// Here is my code AFTER
//
OPUsersTableViewCell *tableCell = [self.groupTableView dequeueReusableCellWithIdentifier:TableCellID];
Note:
self.groupTableView is where the prototype cell is...

Horizontal scrollview within UITableview issue

I created UIScrollview with in UITableViewCell. The scrollView has some pictures to display in horizontally. It works good in one row but I am loading more than one row cells, it makes an issue when one cell is replaced by other cells.
I am using [tableView dequeueReusableCellWithIdentifier:section].
I also gave separate identifier for each row.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *section = [NSString stringWithFormat:#"section%#cell", indexPath.section];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:section];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:section];
NSArray *pageImages = imgs;
}
else
{
NSLog(#"recall");
}
return cell;
}
You don't want to give each cell a different reuse identifier. Change
NSString *section = [NSString stringWithFormat:#"section%#cell", indexPath.section];
to
NSString *section = #"Arbitrary";

iPhone: How to add rows in tableview after tabelview already loaded?

I have implemented "Add to Favourites" functionality for my iPhone application. It works fine except adding cells into my Favourite Table View during runtime. For example, I have given following methods.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
tableView.hidden = YES;
warningLabel.hidden = YES;
// Load any change in favourites
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:kFavouriteItemsKey];
self.favourites = [NSKeyedUnarchiver unarchiveObjectWithData:data];
if([self.favourites count] > 0)
tableView.hidden = NO;
else
warningLabel.hidden = NO;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.favourites count]; // Favorites is a dictionary contains required data
}
- (UITableViewCell *)tableView:(UITableView *)tView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat:#"index: %d",indexPath.row];
return cell;
}
This code works fine and display rows correctly for the first time only! After tableview is loaded and if I add new item(s) in favorites or delete any item(s), it doesn't make any difference to my tableview! I want to display exactly what is available in Favourites dictionary. It seems CellForRowAtIndexPath doesn't get invoked when ViewAppear again. Is there any method for TableView that I can use to achieve my requirements?
I think you've missed to call [tableView reloadData];
The very easy way is to just call [tableView reloadData] whenever you make any changes.
There is also a better (faster for large tables, and possibly animated; more elegant), but much more complicated way which I won't go into unless you decide the reloadData way isn't sufficient for you.