DetailTextLabel behaving strangely - ios

I am trying to set the subtitle label on a UITableViewCell. I have a dictionary containing the pairs of titles and subtitles and the list of keys is stored in self.results. However when I run with the following code:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Search Result Cell" forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Search Result Cell"];
}
cell.textLabel.text = [self.results objectAtIndex:indexPath.row];
cell.detailTextLabel.text = self.resultPairs[[self.results objectAtIndex:indexPath.row]];
NSLog(#"%#", self.resultPairs[cell.textLabel.text]);
The subtitle remains blank, but the NSLog prints the correct output. What is going on here? When I set the detailTextLabel to a constant it works fine.

The problem is that the default cell style does not include a subtitle. If you are using a storyboard, you just need to set the style to Subtitle in Interface Builder.

The solution turned out to be that the strings contained allot of initial whitespace, resulting in them being padded out of the view.

Related

Values entered in custom UITableViewCell UITextField translated to other fields

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;

create UITableViewCell programmatically

I am trying to create a UITableViewCell that contains a UIScrollView that is able to scroll horizontally for each cell in the UITableView.
Everything shows correctly and works well. However, when I scroll constantly up and down on the UITableView, memory usage goes up and up and up and up..... which I think means that I am constantly adding the custom elements over each over when the UITableViewCell is being reused. I would like to know how I can stop this from happening.
Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Configure the cell...
NSDictionary *cellDictionary = [xmlMArray objectAtIndex:indexPath.row];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// code
codeString = [[UILabel alloc] initWithFrame:CGRectMake(15.0, 0.5, 70.0, 40.0)];
codeString.text = [cellDictionary objectForKey:#"Code"];
codeString.backgroundColor = [UIColor clearColor];
// series
addressString = [[UILabel alloc] initWithFrame:CGRectMake(220.0, 10.5, addressString.frame.size.width, 50.0)];
addressString.text = [NSString stringWithFormat:#"PC %#: %#",[cellDictionary objectForKey:#"Number"] ,[cellDictionary objectForKey:#"Street"]];
[addressString sizeToFit]; // Dynamic UILabel width
addressString.backgroundColor = [UIColor clearColor];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UIScrollView *scrollCell = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, cell.frame.size.width, cell.frame.size.height)];
[scrollCell setContentSize:(CGSizeMake((220.0 + addressString.frame.size.width)+15, cell.frame.size.height))];
[scrollCell addSubview:codeString];
[scrollCell addSubview:addressString];
[cell addSubview:scrollCell];
return cell;
}
There seems to be two problems here. I'll try to explain what's actually happening, but you should follow mbm29414's answer on what to do.
In the first part of this method, you are asking for a UITableViewCell using the identifier:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
The next part is to check if you received a cell with this call:
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
This means that if your first line of code DID NOT return a cell-object, then you are instantiating a new one.
Later on in your method, you are instantiating yet another cell:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
UIScrollView *scrollCell (...)
This way you might not actually be reusing the cells, I'm not sure. At the very least, it should not be there. You potentionally allocate double the space each time.
Remove the last instantiation, and that should probably help a little.
The other problem, I think, is that you're adding scrollView and UILabels to your cells' subviews. Your circle of life:
Create cell
Create 2 UILabels
Create ScrollView
Add labels to ScrollView's subview
Add scrollView to Cell's subview
Send cell on it's merry way
When your cell is brought back from the dead during [tableView dequeueReusable..], they still contain the UIScrollView with the UILabel. Your code does not take advantage of that, but rather ignores it. This means that you are adding an ADDITIONAL scrollView with labels into your cell. If you scroll up and down a lot, this means that one single cell can possibly contain 50 different scrollViews, all of them taking the same amount of processing.
This is what happens next:
Get cell from the queue
(this cell already contains UIScollView and UILabels)
Add new scrollView with labels anyway
Send it on it's merry way (now with 2 scrollViews and 4 labels)
To solve this, you should do as mbm29414 suggested, to make your own subclass of UITableViewCell. That way, you can say cell.codeString.text=#"blah";
While you are re-creating a new UITableViewCell each time, you also appear to be endlessly adding UIScrollView and UILabel objects.
First, remove the second call of:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
Second, try subclassing UITableViewCell, making the UI like you like it either in an init method or in IB. Then, make a "setup" method that takes an object and configures each UI element accordingly. That way, you can not only recycle your cells, but also keep from continually creating more UIView subclass instances.
Couple of things.
Your check to see if the table view cell returned by
dequeueReusableCellWithIdentifier: is nil is not necessary, because
that method won't return nil anymore unless you've made a mistake with your identifier. It used to (I think before iOS
6).
Later in the code you're creating a new cell and assigning it to the cell variable which is eventually returned. Why? You already created one, so creating a second is fundamentally wrong.

Getting the title of a pressed/clicked UItableview cell

Okay so I have a view controller with about 5 UITableView Cells inside it. They are all static. What i want to do is click on "Cell One" and then load the "Cell One" PDF. Right now I have it set up with segues in my storyboard so that if you click "Cell One" or "Cell Two" they all open the same PDF. That PDF is loaded in another UIWebView view although i dont know if that matters. So basically can somone help me figure out how I can get the title of the cell that was clicked? Thank you!
In your didSelectRowAtIndex: method you want to do this:
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellTitle = [[cell textLabel] text];
Now you're cell title will be in the cellTitle NSString.
This assumes you haven't used a custom cell. If you have then you just ref your custom label i.e.
YOURCUSTOMCELLCLASS *cell = (YOURCUSTOMCELLCLASS *)[tableView cellForRowAtIndexPath:indexPath];
NSString *cellTitle = [[cell CUSTOMLABEL] text];

Why are my custom cells blank ?

Thanks for the help in advance-
I have a UITableView with a custom cell. If I insert a break point, and log the values for the cell it is correct, but when I execute the code the table view is always blank (but does have the right number of cells)
Cell *cell = (Cell *)[tableView dequeueReusableCellWithIdentifier:[Cell reuseIdentifier]];
if (cell == nil)
{
cell = [Cell cell];
}
StoreData *currentStore = [_storeArray objectAtIndex:indexPath.row];
cell.phoneNumber.text = currentStore.phoneStr;
cell.address.text = currentStore.addressStr;
return cell;
Thanks for the help
Are you certain you registered the custom cell using its class or nib? Also, you are asking to deque based on asking the cell for its identifier - but you must ensure you registered for every class you are trying to deque. Finally, also ensure you set the identifier property inside the storyboard or nib file as well.

How to control the UITableViewCell style programmatically?

Being working with StoryBoard I have this situation, with the code below:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text=[[cityArray objectAtIndex:indexPath.row] valueForKey:#"CELL_TEXT"];
cell.detailTextLabel.text=[[cityArray objectAtIndex:indexPath.row] valueForKey:#"DETAIL_TEXT"];
My tests show me that regardless of the fact that I use UITableViewCellStyleDefault, or UITableViewCellStyleSubtitle when performing the alloc, the two last lines of code above will work.
Those two last lines are only depending on my settings in the StoryBoard (cell style to Subtitle or not).
Now here is my question: How can I programmaticaly control the style of the cells, going from UITableViewCellStyleDefault to UITableViewCellStyleSubtitle and vice versa?
Obviously, changing the alloc only, does not work; and I did not find any property that I could set either.
If you're using a Storyboard with a prototype cell, the cell will not be nil. It will always be created. Either don't use a prototype cell in a Storyboard or allocate a different protoype cell from the Storyboard.

Resources