How to avoid selecting other cells that have the same indexPath - objective-c

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.

Related

Objc how to compare current with previous double values in a tableview cell

I have a tableview that gets refreshed every 10 sec with new double values and i need a mechanism to compare current with previous values but i jam not doing it correctly.
this is what i have now. Can you please propose how to store the current/previous values to get compare after refresh. thx in advance
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierCell forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierCell];
}
Value = [[tempDictionary objectForKey:#"value"] doubleValue];
if (ValueCurrent > ValuePrevious && ValuePrevious !=0.0) {
Label.backgroundColor = [UIColor greenColor];
}
if (ValueCurrent < ValuePrevious) {
Label.backgroundColor = [UIColor redColor];
}
ValuePrevious = Value;
return cell;
}
On my mind all such checks should be performed on model level - in tempDictionary in your case. Add one more key "changed" and set it to #(YES) if new value is different from the previous one when dictionary is updated and to #(NO) otherwise.
Then you can check this value in cellForRowAtIndexPath: and set up background color.
First of all I'm not sure if you need to compare new values of each cell to its previous. If you need to compare new value with previous value respective to each cell then you have to create an NSArray of NSDictionary separately for previous and current values, then compare them each with respective to each cell.
And if you would like to compare only one value when UITableView reloads then you shouldn't compare it in cellForRowAtIndexPath instead compare it when you call [tableView reloadData].
Hope it helps!

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

How to make a-two-column UITableViewController list?

I need to present my table view with a two column list. I read some related posts about making some grid by overriding drawRect (here). However, I'm seeking a simple way to design my cell with IB in nib, then load it and push two cells on each row. The example with drawRect is not appropriate because it involves manual setting of positions. I just need to push those two cells with some autosizing, that's it. Is it possible?
I'm looking for something like (in cellForRowAtIndexPath):
cell.contentView = emptyUIViewContainer;
[cell.contentView addSubview:FirstColumnUIView];
[cell.contentView addSubview:SecondColumnUIView];
I don't need to have two separate nibs for those two columns because every column is of the same format just with some other data. Any ideas?
UPDATE: Intuitively, I'm trying to do something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell1 == nil) {
cell1 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the first cell.
cell1.textLabel.text = ...some text
// Configure the second cell
UITableViewCell *cell2 = [[UITableViewCell alloc] init];
cell2.textLabel.text = ...some text
//set row as container for two cells
UITableViewCell *twoColumnRowView = [[UIView alloc] init]; //initWithFrame:CGRectMake(0, 0, 200, 20)];
cell1.contentView.frame = CGRectMake(0, 0, 100, 20);
[twoColumnRowView addSubview:cell1];
cell2.contentView.frame = CGRectMake(100, 0, 100, 20);
[twoColumnRowView addSubview:cell2];
return twoColumnRowView; // cell;
}
It's just a raw prototype I'm playing with now. But the code crashes at runtime with "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setTableViewStyle:]: unrecognized selector sent to instance"
UPDATE 2. I have changed a code to look more practical. Strange but after several tries I got the app working without crash but with weird black background in all cells. Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *FirstCellIdentifier = #"FirstCellIdentifier";
static NSString *SecondCellIdentifier = #"SecondCellIdentifier";
// initialize first cell
UITableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:FirstCellIdentifier];
if (cell1 == nil) {
cell1 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:FirstCellIdentifier] autorelease];
}
//initialize second cell
UITableViewCell *cell2 = [tableView dequeueReusableCellWithIdentifier:SecondCellIdentifier];
if (cell2 == nil) {
cell2 = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SecondCellIdentifier] autorelease];
}
cell1.textLabel.text = ...data
cell2.textLabel.text = ...data
UITableViewCell *twoColumnRowView = [[UITableViewCell alloc] init];
[twoColumnRowView addSubview:cell1];
//cell2.contentView.frame = CGRectMake(100, 0, 100, 20);
[twoColumnRowView addSubview:cell2];
return twoColumnRowView; // cell;
}
I'm not reusing twoColumnRowView but both other does do.
You can't (or at least, shouldn't) put two table views next to each other. And, as you already know, a table view only ever has a single column.
However, you can put as much data as you want in each cell.
You can do most of this in Interface Builder. Create a XIB with a UITableViewCell. Drag and drop a couple of UILabels into the right place. You could update the labels by finding them with the viewWithTag: method, but it would be better to create a custom UITableViewCell class with properties pointing to each label.
Since tables are so central to UIKit, there are a lot of samples in Apple's documentation set and some good WWDC talks. You can download the videos from iTunes.
Hope this will help you...
http://www.iphonedevx.com/?p=153
else the best way is to put two table views side by side, if they need to scroll independently.
Hope this will help you...

UILabel text overlapping on update?

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.