UILabel text overlapping on update? - cocoa-touch

In my app I change the value of a text label from an initial value of 0 and increment it on a touch event. Sometimes, but not all the time, the new value will be overlayed over the 0, which is not cool..
This is the relevant code:
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UILabel *label = (UILabel *)[cell viewWithTag:1000];
label.text = qtyString;
I've tried removing the label from the view, then adding another with the new value, but it didn't affect the problem at all. When I scroll the cell (the labels are part of a table cell) out of the screen and back in, the labels display correctly. Oh, and I've also tried doing
[tableView reloadData];
And it works better, but if I select a cell and then scroll while it is higlighted it poops out on that cell.
Please help :(

check the "clears graphics context" works for me, i carelessly deselected it at first~~

Under your UILabel options UNCHECK 'opaque', that will fix it.

I had the same problem with UILabel's text getting all jumbled, I just read the other solutions, went to IB, then checked "Clear context before drawing", and that solved it!

Changing opaque doesnt change it altho it would have been logic. What you can do if giving your label an exact height .. This height will match your well height. If you are using
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80; //returns floating point which will be used for a cell row height at specified row index
}
Like i did then make the height of the label 80 as well that will stop it ..

imho, the best way to go around this is to add an else to:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}else {
NSArray *cellSubs = cell.contentView.subviews;
for (int i = 0 ; i < [cellSubs count] ; i++) {
[[cellSubs objectAtIndex:i] removeFromSuperview];
}
}
Hope this helps.

In my case, changing Opaque to NO solve the problem of updating the UILabel.text
I create the uilabel in the awakeFromNib.

Related

How to avoid selecting other cells that have the same indexPath

I've been struggling with this issue for weeks and still have not found one solution. No one really gave me an answer on SO and have not found anything that helps my issue either.
When making a change of a cell's content's color, position, whatever, other cells with the same indexPath also get modified.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object{
static NSString *simpleTableIdentifier = #"cell";
self.cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (self.cell == nil) {
self.cell = [[SearchCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
This is how I create cells. Help..!
EDIT
This is a slide-out view implemented in each cell. When you swipe to right on a cell, it shows up from the left but even though only the selected cell's content should be modified, several other cell's slide-out menu also come out.
This is how I implement slide-out menu in my custom cell class.
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.optionView = [[OptionView alloc]initWithFrame:CGRectMake(0, 0, self.contentView.frame.size.width , self.contentView.frame.size.width)];
self.optionView.delegate = self;
[self.contentView addSubview: self.optionView];
OptionView' delegate - called when swiped to the right
-(void)handleGesture:(UISwipeGestureRecognizer*)shouldOpenMenu{
POPSpringAnimation *anim = [POPSpringAnimation animation];
anim.property = [POPAnimatableProperty propertyWithName:kPOPViewFrame];
anim.toValue = [NSValue valueWithCGRect:CGRectMake(-self.frame.size.width/4, 0, self.optionView0.frame.size.width, self.optionView0.frame.size.height)];
anim.springBounciness = 11;
anim.springSpeed = 5;
[self.optionView0.layer pop_addAnimation:anim forKey:#"spring0"];
First, each tableview cell has different index path.
Second, you never want to save cells at class level properties. Create them locally and return from cellForIndexPath:. Your table view will take care of the cell thereon.
Third, and very important, cells are reused. So, you should reset the cell before using it. For instance, if you are setting cell colour to red in some condition and then you move the table down and this cell gets discarded and new cell is rendered by re-using the discarded cell. You would want to reset the cell colour to clear if you are not setting cell colour for that row.
Follow these rules and you should be able to fix your issue.

Adding label/button to UICollectionView - Footer or not?

I have a collectionView that displays an array of images in a single, horizontal layout. I'm trying to add a UILabel under each cell. I assumed the best/easiest way to do this would be to add a footer view/supplementary view for each cell. Therefore, I'm overriding viewForSupplementaryElementOfKind. I have an array of images names that correlate to the array of images. So I'm just hoping the see the image name as the label for each each cell. However, all labels and names are overlapping on the first cell. Also, the footer view doesn't come into view until I scroll to the last image/cell, so I don't see the overlapping labels on the first cell until I scroll to the end. I know the issue is in my viewForSupplementaryElementOfKind implementation, but I'm not sure how to correct it. Can someone please advise? Thanks in advance!!
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
NSLog(#"viewForSupplementaryElementOfKind");
static NSString *FooterCellIdentifier = #"FooterView"; // string value identifier for cell reuse
FooterViewCell *footerView;
if (kind == UICollectionElementKindSectionFooter) {
NSLog(#"*******Element Kind is a footer!*******");
footerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter
withReuseIdentifier:FooterCellIdentifier forIndexPath:indexPath];
for (int i = 0; i < [self.imagesArray count]; i++) {
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.myCollectionView.frame.origin.x/2, self.myCollectionView.frame.origin.y/2, CellWidth, 20)];
//testLabel.text = [self.imageNames objectAtIndex:indexPath.row];
testLabel.text = self.imageNames[i];
[self.myCollectionView addSubview:testLabel];
}
return footerView;
} else {
NSLog(#"*******Element Kind is NOT a footer!*******");
return nil;
}
}
Header and footer views on UICollectionView are only relative to sections.
Since the labels are supposed to identify the images (the model), you should build your UICollectionViewCell with the label and image view inside, as subviews. The easiest way is doing it inside a storyboard, with prototype cells on the collection view.

reloading a uitableview starts at the 2nd row (or not at the first row)

Uitableview problem again. Whenever I reload my data, the tableview would reload but it seems like the data will not start at the first row. Please refer to the image below.
I tried the following after the reload of data but still no success:
[self.tableView reloadData];
// this or the other one ... [self.tableView setContentOffset:CGPointZero animated:NO];
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
This is how I positioned the uitableview on viewdidload
self.tableView.frame = CGRectMake(450, 20, self.tableView.frame.size.width, self.tableView.frame.size.height - 20);
EDIT 1:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"SearchResultCell";
User *user = [users objectAtIndex:indexPath.row];
UserTableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UserTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.name.text = [NSString stringWithFormat:#"%# %#", user.firstName, user.lastName];
return cell;
}
Based on your comments, your table is being resized incorrectly when you are rotating the device to landscape mode. In your storyboard, you need to set the autoresizing on the table view in order for it to properly resize the way that you want.
Here is a good starting point for something like this:
Notice just above the Autosizing label, it shows a bunch of red bars (called springs and struts). I have them all turned on, which will maintain the distance from the edge of the superview and allow the object to change its' size in order to keep those distances the same. This should be close to what you want, and if not then you can play around with the different combinations until you get what you want.
You turn each part of it on and off by clicking on the red line.
For more details, take a look at this question: Autoresizing masks programmatically vs Interface Builder / xib / nib

Add a second subtitle row to UITableViewCellStyleSubtitle

I have already made a custom class with the init:
if(self = [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier]) {
}
As I wanted to add a blue texted label to the right hand side of the cell and have it go right when selected otherwise it looked odd when highlighted:
self.sizeTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.contentView.frame.size.width-110, 0.0, 100.0, 44.0)];
self.sizeTextLabel.textAlignment = NSTextAlignmentRight;
self.sizeTextLabel.backgroundColor = [UIColor whiteColor];
self.sizeTextLabel.textColor = [UIColor colorWithRed:81/255.0 green:102/255.0 blue:145/255.0 alpha:1.0];
self.sizeTextLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:self.sizeTextLabel];
There is probably a better way of doing that ^
What I would like to do is add another label that is effectively another subtitle row, I then increase the height of the row when the cell is created with the heightForRowAtIndexpath method.
Problem: When I add a new label 'row' to the content view, it does not get higher (the default views shift to the middle of the view). How do I create and position it correctly below the subtitle view? If I were to change the first subtitle to multiline it would be nice if the second label knew what to do.
I wish cocoa had relative positioning. Or I haven't found it yet!
You can make the detail text label multi line and add your two strings to the one label. In this example, my data has three keys in its dictionaries, "main" for the main label text, and "detail1 and "detail2" for the two subtitle strings.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSDictionary *object = _objects[indexPath.row];
cell.textLabel.text = object[#"main"];
NSString *concat = [NSString stringWithFormat:#"%#\n%#",object[#"detail1"],object[#"detail2"]];
cell.detailTextLabel.numberOfLines = 2;
cell.detailTextLabel.text = concat;
return cell;
}
You can make a custom cell with interface builder and use it instead of UITableViewCell.
Check this: http://www.backslashtraining.com/blog/2012/3/10/ios-5-tip-of-the-week-custom-table-view-cells.html

UITableView subview appears in wrong section when scrolling?

In a UITableView I add a UIView as subview but ONLY for section 1. Section 1's content is loaded from a plist and the plist contains mutable content. If there are enough rows to allow scrolling, then the following happens: I scroll to the bottom, and back up, and the UITextField appears randomly on some of section 0's cells. I have no clue why this is happening! So what i do is this (in ´cellForRowAtIndexPath´):
if (indexPath.section == 0) {
//do stuff
}
else if (indexPath.section == 1) {
d = [UIView alloc] init];
[cell.contentView addSubview:d];
}
and this gets totally messed up when I scroll. The subviews appear in section 0 where they shoudnt, and on didSelectRowAtIdexPath I reload for section 1 and then subviews even appear twice (over each other)... Its a complete MESS! Please, Please help.......
Without seeing any code this seems to be an issue pertaining to reusable cells. What happens is that the cells that have scrolled off the screen are reused for the new content that is to be shown. So i reckon you need to make a distinction in cellForRowAtIndexPath for section 0 and 1 and basically use different set of cells for them.
EDIT: Ok ima give a shot to your problem here
UITableViewCell *cell;
if (indexPath.section == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:#"CellWithoutSubview"];
if (cell ==nil ) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewStylePlain reuseIdentifier:#"CellWithoutSubview"] autorelease];
}
//do stuff with cell like set text or whatever
}
else if (indexPath.section == 1) {
cell = [tableView dequeueReusableCellWithIdentifier:#"CellWithSubview"];
if (cell ==nil ) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewStylePlain reuseIdentifier:#"CellWithSubview"] autorelease];
d = [[UIView alloc] init];
[cell.contentView addSubview:d];
[d release];
}
}
return cell;
So now you'll have two types of cells for the tableview that'll be reused one without the subview and one with the subview.
You must be using dequeueReusableCellWithIdentifier. The purpose of dequeueReusableCellWithIdentifier is to use less memory. If the screen can fit 4 or 5 table cells, then with reuse you only need to have 4 or 5 table cells allocated in memory even if the table has 1000 entries.
So the subviews in UITableViewCell are also cached. So when the cell is reused, you need to clean out the old view & then put in the new content.
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier: #"your-id"];
if (cell)
{
//reusing old cell. reset all subviews before putting new content.
}
else
{
//Create a fresh new cell
}
You should use switch instead:
switch ( indexPath.section )
{
case 0:
{
/* do soemthing */
}
break;
case 1:
{
d = [UIView alloc] init];
[cell.contentView addSubview:d];
}
break;
}