Values entered in custom UITableViewCell UITextField translated to other fields - ios

So, this is going to be a very strange problem to address. I will try to be as specific as possible.
Here is a snippet from my UITableViewController:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"miscCell";
JASMiscConfigurationTableViewCell *cell = ((JASMiscConfigurationTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier]);
if (cell == nil) {
cell = [[JASMiscConfigurationTableViewCell alloc] init];
}
JASMiscellaneous *misc = [((NSMutableArray *)[_miscellaneousList objectAtIndex:indexPath.section]) objectAtIndex:indexPath.row];
[cell.itemNameLabel setText:misc.itemDescription.productCostDescription];
if ([misc.itemQuantity doubleValue] > 0) {
[cell.itemQuantityField setText:[misc.itemQuantity stringValue]];
}
return cell;
}
JASMiscConfigurationTableViewCell is just a custom UITableViewCell with a label and textfield.
The issue at hand here is:
If I enter a value into a UITextField in the cell and I scroll down the page, the value entered literally translates down the page as I scroll. It always manages to rest directly inside the UITextField of another row cell when I stop scrolling. The value entered does not disappear when it leaves its original UITextField, it floats at the forefront of the screen. This is not solely a GUI bug, either. When I iterate through the cells for their values to store them in objects, the UITextField the value has translated to is actually holding the value. What's stranger still is that the original UITextField the value was entered in is also still holding the value. When I leave the screen and reenter, both text fields with hold the value.
I'm sorry if this sounds confusing. It's confusing to me. If you need any clarification I would be happy to provide it. Help is appreciated.

Normal allocation cell = [[JASMiscConfigurationTableViewCell alloc] init]; is different from allocating with -reuseIdentifier like..
cell = [[JASMiscConfigurationTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
it is possible that
JASMiscConfigurationTableViewCell *cell = ((JASMiscConfigurationTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier]);
keeps on using the previous cell.
try this:
static NSString *cellIdentifier = #"miscCell";
JASMiscConfigurationTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]);
if (cell == nil) {
cell = [[JASMiscConfigurationTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
About the held/replaced when the cell leaves and reenters view
you are missing the else statement:
if ([misc.itemQuantity doubleValue] > 0) {
[cell.itemQuantityField setText:[misc.itemQuantity stringValue]];
}
//set value if the condition is not met.
cell.itemQuantityField.text = #"no";

Table views re-use cells. When a cell is scrolled offscreen it is added to a queue, and will be re-used for the next cell to be scrolled onscreen. That means your configuration code in tableView:cellForRowAtIndexPath: method will be run again on the same cell at different index paths.
That means you need to update the itemQuantityField's text every time this runs, not just when you have a quantity above zero. Otherwise the cell will still have the text from when it was used previously at a different index path.
I've rewritten your if ([misc.itemQuantity doubleValue] > 0) {...} so that the text is set to nil if the itemQuantity is zero or less. The same could be achieved with an else clause.
BOOL validQuantity = [misc.itemQuantity doubleValue] > 0;
cell.itemQuantityField.text = validQuantity ? [misc.itemQuantity stringValue] : nil;

Related

Duplicate rows on uitableview when scrolling with custom cell

Here is my code :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier=#"menucell";
MenuCell *cell = (MenuCell*) [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (cell==nil)
cell= [[MenuCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] ;
MenuModel *resturntent = (self.menuList)[indexPath.row];
cell.foodNameLbl.text = resturntent.MenuName;
cell.priceLbl.text = [NSString stringWithFormat:#"%# %#",#"$" , resturntent.MenuRate];
cell.foodImage.image = [UIImage imageNamed:#"full_breakfast.jpg"];
return cell;
}
While scrolling uitextfields values gets duplicates .
I need help to fix this issues
When you use dequeueReusableCellWithIdentifier, your cells will be reused. This means when the user scrolls the tableview, a cell which moves out of the screen will be reused to display the contents of a cell which is about to move onto the screen.
Even though this helps in saving memory, the problem it causes is the that the cell needs to be prepared for display before it is loaded with the content of the new cell.
In your case, it seems you need to maintain the values the user has entered in a textfield of a cell.
So to fix your problem, if there are not that many cells in the tableview, simply stop reusing the cell. Else whenever the user enters a value in the textfield of a cell, save it in an array (array of 'MenuModel' in your case). And fetch the value from from the model and set it to your textfield in the cellForRowAtIndexPath method like your have set values for other labels.

UITableViewCells reverting back to default or other values

So I've created a TableView as below, but I have quite an annoying problem.
When I come to this VC, I click Choose User, and I selected user Atoshum.
When I scroll down, this top cell goes off screen as I scroll through the bottom cells.
When I scroll back up, the cell has reverted to a default (or occasionally, takes the value of another cell).
I make the cells as such.
static NSString *CellIdentifier = #"Cell";
DMSDrugInstanceCell *Cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!Cell) {
Cell = [[DMSDrugInstanceCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Cell.chooseUserButton.tag = indexPath.row;
[Cell.chooseUserButton addTarget:self
action:#selector(performSegue:)
forControlEvents:UIControlEventTouchUpInside];
return Cell;
In the cell creation you dont ever set any values. All you do is set the tag and then add an event target. If you want it to keep the choose, you need to store/save that choice when it is made and then in the cell create, set it based on that saved value.
you are reusing table cell. So every time your cell reload then you need to set value in cell.
in cellForRowAtIndexPath method , you need to set value in cell according to index path.
This is because the UITableView do not create the new cells for total number of elements. Rather it re-uses the cells which are off the visibility. Hence you feel that your data is reset or getting reflected on some other cell.
The best approach is to store all your data in some Array (let it be tagDataArray) and then set your cells as
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
DMSDrugInstanceCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[DMSDrugInstanceCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Cell.chooseUserButton.tag = [tagDataArray objectAtIndex:indexPath.row];
...
...
return Cell;
}

Random display of UIImageView in UITableView cells when scrolling

I have a custom separator in every cell(added it in the IB), I want to delete/hide it based on a specific condition:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier= #"satellite";
SatellitesCell *cell= [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell) {
cell =[[SatellitesCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if([[arrayofRadios objectAtIndex:indexPath.row] isEqualToString:#""]){
[cell.separatorImage removeFromSuperview];
cell.separatorImage = nil;
}
cell.satelliteName.text=[arrayofSatellitesName objectAtIndex:indexPath.row];
return cell;
}
When launching the view, all is okay, but the problem is when scrolling, the separator(the UIImageView) is displaying randomly in every cell.
If I understand you correctly, you want to use the same cell prototype but have it look different based on the data. If this is the case, then I wouldn't remove the separatorImage from the superview, just hide it (eg. cell.separatorImage.hidden = YES;). This way in the else case of that if statement, you can unhide it (eg. cell.separatorImage.hidden = NO;).
Or I suppose, if you have a specific reason for removing it from the superview, then just be sure to create an else statement for that if statement, and add it back to the cell (eg. [cell addSubview:cell.separatorImage];).

When creating my UITableViewCells, why is the init never called? (Resulting in blank cells?)

In my UITableView, I recently changed the structure of the cell from formerly just putting UILabels in the contentView of the cell, to adding two UIViews (CellFront and CellBack, on top of one another) into the contentView (so I can achieve a sliding effect by sliding the top one off and revealing the lower one) and adding the UILabels to the top UIView.
However, now, for whatever reason, the cells never get init'd and as a result my UITableView is full of blank cells.
My cell gets created as follows (ArticleCell is a subclass of UITableViewCell):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = nil;
ArticleInfo *articleInfo = [self.fetchedResultsController objectAtIndexPath:indexPath];
// Checks if user simply added a body of text (not from a source or URL)
if ([articleInfo.isUserAddedText isEqualToNumber:#(YES)]) {
CellIdentifier = #"BasicArticleCell";
}
else {
CellIdentifier = #"FullArticleCell";
}
ArticleCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[ArticleCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// If the user simply added a body of text, only articlePreview and progress has to be set
cell.preview = articleInfo.preview;
// If it's from a URL or a source, set title and URL as well
if ([articleInfo.isUserAddedText isEqualToNumber:#(NO)]) {
cell.title = articleInfo.title;
cell.URL = articleInfo.url;
}
return cell;
}
But I set a breakpoint on the initWithStyle method above within the if statement and it never gets called:
What would cause this? I'm deleting the app and building it from scratch every time, so data is definitely being added to the UITableView, but all the cells are blank. And I can tell a bunch of cells are being added as I have disclosure indicators on all of them, and the table view just gets filled with empty cells with the indicators only.
What am I doing wrong?
try
ArticleCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
instead of
ArticleCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
the first one is the old standard way. It will not create a cell for you. While with the second a cell will be created form the storyboard. So if you use storyboards you should use indeed the method you are using now, but it will never go info the if branch, as the cell will never be nil.
when instantiating form storyboard, initWithStyle:reuseIdentifier: is never called. Either set everything up in -initWithCoder: or -layoutSubviews

iOS xcode, adding UILabel subview to custom table cell, label text does not update on screen

I've created a custom UITableViewCell class, and used the layoutSubviews method to add a custom label. Like this:
- (void)layoutSubviews
{
[super layoutSubviews];
if (statusLabel == nil)
{
statusLabel = [[UILabel alloc]initWithFrame:CGRectMake(430.0, 10.0, 100.0, 20.0)];
[statusLabel setTextAlignment:UITextAlignmentRight];
[statusLabel setText:#"Status, set in code"];
statusLabel.tag = 1;
[self.contentView addSubview:statusLabel];
}
}
As you can see, I have set the initial text of the label to "Status, set in code".
In the table view controller I set the text for this custom label in the cellForRowAtIndexPath method, like so:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
int index = [indexPath row];
NSString *introducerString =[introducers objectAtIndex:index];
NSArray *parts = [introducerString componentsSeparatedByString:#","];
static NSString *MyIdentifier = #"Requester";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[DanceCardCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:MyIdentifier] autorelease];
}
UIImage *image = [UIImage imageNamed:#"1.jpg"];
[cell.imageView setImage:image];
cell.textLabel.text = [parts objectAtIndex:1];
cell.detailTextLabel.text = #"Some text";
UILabel *statusLabel = (UILabel *)[cell viewWithTag:1];
statusLabel.text = #"Did it!";
return cell;
}
I'm using one table view to display two lists, depending on which of two buttons is pressed. When a button is pressed the appropriate table view controller is attached to the table view, and the reloadData method is called to trigger display of the new data. The new data does display, but the custom label text, which should read "Did it!" reads "Status, set in code ...", until I switch lists again twice.
How can I get the new text for the custom label to update straight away? I have checked the official documentation and cannot find any reference to refreshing a cell's display after updating its custom content.
Here is a screen shot to demonstrate what happens: http://www.dsbsystems.co.uk/images/xcode1.png
You're initializing the cell and immediately attempting to find the statusLabel with tag 1 inside it. layoutSubviews hasn't had the opportunity to be called yet, and so the label hasn't been created and added. (I suggest overriding the designated initializer method on your table view cell and creating the label there.)
Because of this, when you try to pull out statusLabel, it becomes nil because there's no such view, and messaging (calling a method on) nil simply does nothing (actually, it returns nil). You will need to watch out for this going forward if you're used to things blowing up with e.g. null reference exceptions.
When the cell is requested again, a new cell isn't needed because it's available from the reuse queue, and the label will be found correctly.

Resources