UITableView not scrolling after i did this - ios

I'm new to iOS developing. I have a UITableViewCell which has three buttons and they were not appearing to be pressed to touch. I implemented the following code. The pressing appeared to have been solved but the scrolling have been disabled. Here's my code to make buttons appear to be pressed on touch. The loop in the code is important otherwise the table will not behave the way I want it to. Here's my code for cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString *CellIdentifier = #"customCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UILabel *textLabel = (UILabel *) [cell.contentView viewWithTag:5];
switch ([indexPath section]) {
case 0:
textLabel.text = [patientRoom objectAtIndex:[indexPath row]];
break;
case 1:
textLabel.text = [patientsBathroom objectAtIndex:[indexPath row]];
break;
}
if (shown){
if (selectedIndexPath.row == indexPath.row)
comments.hidden = NO;
}
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
// Configure the cell...
for (id obj in cell.subviews){
if ([NSStringFromClass([obj class]) isEqualToString:#"UITableViewCellScrollView"]){
UIScrollView *scroll = (UIScrollView *) obj;
scroll.delaysContentTouches = NO;
break;
}
}
return cell;
}

Related

Changing the default TableViewCell to custom subclass on button click

In a specific row I apply the default UITableViewCell class with a text label and an accessory button. When the accessory button is clicked, the cell is expanded and I want to change the UITableViewCell to a custom subclass I have created. However even if the cell is expanded, it won't switch to the custom subclass. Any ideas what to fix?
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat result;
switch ([indexPath row])
{
case 2:
{
if ([indexPath isEqual:expandedRow]) {
return 100;
} else {
return 42;
}
}
return result;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier;
NSString *CellIdentifierexp;
UITableViewCell *cell;
if (cell == nil) {
if (indexPath.row == 2) {
if ([indexPath isEqual:expandedRow]) {
cell = [[ExpandedCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierexp];
}else{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
switch ([indexPath row])
{
case 2:
{
if ([indexPath isEqual:expandedRow]) {
NSLog(#"bike");
ExpandedCell *expandedcell = (ExpandedCell *)cell;
[expandedcell.text setText:self.descr];
NSArray *indexPathArray=[NSArray arrayWithObject:indexPath];
[self.tableview reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
} else {
cell.textLabel.text = #"Description";
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.textColor = UIColorFromRGB(0x2d5b3b);
// accessory type image
UIImage *image = [UIImage imageNamed:#"greenarrow.jpg"]; //or wherever you take your image from
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0,0, image.size.width, image.size.height)];
[button setBackgroundImage:image forState:UIControlStateNormal];
[button addTarget:self action:#selector(accessoryButtonTapped:withEvent:) forControlEvents:UIControlEventTouchDown];
button.userInteractionEnabled = YES;
cell.accessoryView = button;
}
break;
}
return cell;
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
switch ([indexPath row])
{
case 2:
{
NSLog(#"Detail Disclosure Tapped");
expandedRow = indexPath;
[tableview beginUpdates];
[tableview endUpdates];
}
}
}
- (void) accessoryButtonTapped: (UIControl *) button withEvent: (UIEvent *) event
{
NSIndexPath * indexPath = [self.tableview indexPathForRowAtPoint: [[[event touchesForView: button] anyObject] locationInView: tableview]];
if ( indexPath == nil )
return;
[self.tableview.delegate tableView: self.tableview accessoryButtonTappedForRowWithIndexPath: indexPath];
}
Wow, you're doing something terribly wrong in here:
ExpandedCell *expandedcell = (ExpandedCell *)cell;
[expandedcell.text setText:self.descr];
NSArray *indexPathArray=[NSArray arrayWithObject:indexPath];
[self.tableview reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
What you should do is slightly different. On a button tap you just call the [self.tableview reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone]; then in the cellForRowAtIndexPath you should return the custom cell of your subclass in the method if the indexPath matches. No need to update the tableView there.
And need I say that this looks like a very very strange switch statement to me:
switch ([indexPath row])
{
case 2:
{
NSLog(#"Detail Disclosure Tapped");
expandedRow = indexPath;
[tableview beginUpdates];
[tableview endUpdates];
}
}
I would simply put it like this:
if (indexPath.row == 2){
NSLog(#"Detail Disclosure Tapped");
expandedRow = indexPath;
[tableview beginUpdates];
[self.tableview reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableview endUpdates];
}
Running the code
expandedRow = indexPath;
[tableview beginUpdates];
[tableview endUpdates];
when the accessory button is tapped will only ask the table view to update the row heights, it won't actually request a new cell for any row, so no cell type change will happen (until you scroll the row off screen and then back on again).
So, you need to actually reload the selected row, not just begin and end updates.
this here...
UITableViewCell *cell;
if (cell == nil) {
Local vars dont init to nil , they start as garbage, maybe nil , maybe not.
Either way you probably are not making it into the branch.
You are going to want to dequeue a cell from the table depending on whether its an expanded row or not
UITableViewCell *cell = nil;
if(thisIsAnExpandedRow) {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierexp];
if(!cell) {
cell = [[ExpandedCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierexp];
}
}
else {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
}

I have a UITextField for customCell for UITableView. On TapGesture of UITextField, I need to display checkmark on right side of UITableViewCell

I have a UITextField for customCell for UITableView.
On TapGesture of UITextField, I need to display checkmark on right side of UITableViewCell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
PreferenceCellWithTextBox *cell = (PreferenceCellWithTextBox *)[tableView dequeueReusableCellWithIdentifier:#"PreferenceCellIdentifier"];
if (cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"PreferenceCellWithTextBox"
owner:nil
options:nil];
for (id currentObject in topLevelObjects)
{
if ([currentObject isKindOfClass:[UITableViewCell class]])
{
cell=(PreferenceCellWithTextBox *)currentObject;
break;
}
}
if([self.checkedIndexPath isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(forwardToDidSelect:)];
[cell.userIdTextField addGestureRecognizer:tap];
}
return cell;
}
Here, I am writing for Tap Gesture. and It gets called only once. It should not happen like that. It should get called whenever I may touch UITextField which is on UITableViewCell.
-(void)forwardToDidSelect:(UITapGestureRecognizer *)tap
{
[self tableView:self.userIdSuggestiontableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
}
Here, I have written code for did select row. On Select of any row, I want to display the Checkmark.and remove checkmark from previous one.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(self.checkedIndexPath)
{
PreferenceCellWithTextBox* uncheckCell =(PreferenceCellWithTextBox *) [tableView
cellForRowAtIndexPath:self.checkedIndexPath];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
if([self.checkedIndexPath isEqual:indexPath])
{
self.checkedIndexPath = nil;
}
else
{
PreferenceCellWithTextBox* cell = (PreferenceCellWithTextBox*)[tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self.checkedIndexPath = indexPath;
}
}

UIswitch in a table cell reused

I have a problem with uiswitch in my UITableViewCell that whenever i change a switch value in a specific cell that belongs to a specific section. All other sections cells that have same inexPath.row change . Please help ?
Here is my code of cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//UISwitch *switchview = nil ;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
UISwitch *switchController = [[UISwitch alloc] initWithFrame:CGRectZero];
CGRect switchFrame = switchController.frame;
NSString *str = [[self.SwitchArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
NSLog(#"string in cell%#", str);
//set its x and y value, this you will have to determine how to space it on the left side
switchFrame.origin.x = 50.0f;
switchFrame.origin.y = 10.0f;
switchController.frame = switchFrame;
[switchController addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[cell addSubview:switchController ];
[addSubview:switchController];
if ([[[self.SwitchArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row ]isEqualToString:#"ON"])
{
switchController.on=YES;
}
else
{
switchController.on=NO;
}
return cell;
}
And here is SwitchChangedEvent:
-(void)switchChanged:(UISwitch *)sender
{
UITableViewCell *cell = (UITableViewCell *)[sender superview];
NSIndexPath *index=[mainTableView indexPathForCell:cell];
if (sender.on)
{
[[self.SwitchArray objectAtIndex:index.section] replaceObjectAtIndex:index.row withObject:#"ON"];
NSString *word= [[self.mainArray objectAtIndex:index.section ] objectAtIndex:index.row];
}
else
{
//call the first array by section
[[self.SwitchArray objectAtIndex:index.section] replaceObjectAtIndex:index.row withObject:#"OFF"];
NSString *word= [[self.mainArray objectAtIndex:index.section ] objectAtIndex:index.row];
}
[padFactoids setObject:[NSKeyedArchiver archivedDataWithRootObject:SwitchArray] forKey:#"savedArray"];
[padFactoids synchronize];
}
You have two main problems:
This code is wrong:
[cell addSubview:switchController ];
Never add a subview to the cell; add it only to the cell's contentView.
You are adding the switch every time through cellForRowAtIndexPath:. But these cells are being reused. So some cells already have the switch. Thus you are adding many switches to some cells.
As already pointed out by others, you're adding multiple switches to each cell. FTFY:
UISwitch *switchController = nil;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
switchController = [[UISwitch alloc] initWithFrame:CGRectZero];
switchController.tag = 'swch';
CGRect switchFrame = switchController.frame;
//set its x and y value, this you will have to determine how to space it on the left side
switchFrame.origin.x = 50.0f;
switchFrame.origin.y = 10.0f;
switchController.frame = switchFrame;
[switchController addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[cell.contentView addSubview:switchController];
}
else
{
switchController = (UISwitch*)[cell.contentView viewWithTag: 'swch'];
NSAssert(switchController != nil, #"how?");
}
NSString *str = [[self.SwitchArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
NSLog(#"string in cell%#", str);
switchController.on = [str isEqualToString:#"ON"];
return cell;
If you look, I think you will find that you are building up multiple switches and on each cell.
As cells get reused, you add a new switch but do not remove the old one. I think this my be at least part of the cause of your problem.
UPDATE
I think I would handle this a bit differently than others. I think it will be easier for #AlanoudAldrees to remove the old switch.
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
else
{
for (UIView *view in cell.subviews)
if ([view isKindOfClass:[UISwitch class]])
[view removeFromSuperview];
}

Working with some of UITableViewCell

How to select several UITableViewCell (as a checkmark but with my own style) and then do something with selected items?
As a checkmark (or something else) I would like to use UIImageView:
To add to Pandu1251's answer, if you want to use your own check mark image, you can set a custom accessory view and follow the same logic that he has specified.
To set a custom accessory view, use
cell.accessoryView = myAccessoryView; //myAccessoryView is a UIImageView holding your custom check mark image
-(void)tableView:(UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath
{
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if (thisCell.accessoryType == UITableViewCellAccessoryNone)
{
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
for(int i=0;i<[Array count];i++)
{
thisCell.accessoryType = UITableViewCellAccessoryNone;
}
thisCell.accessoryType = UITableViewCellAccessoryNone;
}
}
Now try this......
Just do as follow. For that you have to take NSMutableArray. i have taken arrMethodsToBeStored here.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
cell.textLabel.textColor=[UIColor darkGrayColor];
cell.textLabel.font= [UIFont fontWithName:#"Arial Rounded MT Bold" size:15.0];
Scope_RepairMethod *scpObj=[repairMethodArr objectAtIndex:indexPath.row];
cell.textLabel.text= scpObj.strRepairMethod;
if([self.checkedIndexPath isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// NSString *selID;
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
Scope_RepairMethod *scpObj=[repairMethodArr objectAtIndex:indexPath.row];
if (newCell.accessoryType == UITableViewCellAccessoryNone)
{
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
[arrMethodsToBeStored addObject:scpObj.strRepairMethod];
}
else
{
newCell.accessoryType = UITableViewCellAccessoryNone;
[arrMethodsToBeStored removeObject:scpObj.strRepairMethod];
}
NSLog(#"selected method arr==== %#",arrMethodsToBeStored);
// I want to enable my save button only if one or more values from table are selected
if(arrMethodsToBeStored.count > 0)
saveBtn.enabled=true;
else
{
saveBtn.enabled=false;
}
}

UITableView with two custom cells (multiple identifiers)

I am trying to put a cell as a space between each cell - which will be hidden by setting alpha = 0. In my table, the space cells will be for rows that are odd.
Note that the actual cell height is 85, but the hidden cell height (ie space between cells) is 20.
The problem is that the space cell height is 85, but not 20, I don't know why. Maybe the cell is not loaded correctly.
Cell here is the UITableViewCell - the actual cell - with identifier 'Cell'.
Cell2 is the space with identifier 'Space'.
Each class above has its own UITableViewCell class and the XIB files are also assigned to each of them. The identifier is also set in the IB for each Xib.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier1 = #"Cell";
static NSString *CellIdentifier2 = #"Space";
Cell *cell = (Cell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if(!cell)
{
NSArray *ar = [[NSBundle mainBundle] loadNibNamed:#"CellView" owner:nil options:nil];
for (id obj in ar)
{
if ([obj isKindOfClass:[Cell class]])
{
cell = (Cell *)obj;
break;
}
}
}
if (indexPath.row % 2 == 1)
{
Cell2 *cell2 = (Cell2 *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (!cell2)
{
NSArray *ar = [[NSBundle mainBundle] loadNibNamed:#"Cell2" owner:nil options:nil];
for(id obj in ar)
{
if([obj isKindOfClass:[Cell2 class]])
{
cell2 = (Cell2 *)obj;
break;
}
}
// Method 1
cell2 = [[Cell2 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2];
// Method 2
//cell2 = [[Cell2 alloc] init];
// Method 3
//cell2 = (Cell2 *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
[cell2.contentView setAlpha:0];
// prevent selection and other stuff
[cell2 setUserInteractionEnabled:NO];
}
return cell2;
}
else
{
// Configure the actual cell
}
return cell;
}
* I've renamed some of your NIB/Class names for a better understanding. *
First, you should register each cells' NIB:
- (void)viewDidLoad{
[super viewDidLoad];
static NSString *CellIdentifier1 = #"ContentCell";
static NSString *CellIdentifier2 = #"SpaceCell";
UINib *nib = [UINib nibWithNibName:#"CellViewNIBName" bundle:nil];
[self.tableView registerNib:nib forCellReuseIdentifier:CellIdentifier1];
nib = [UINib nibWithNibName:#"CellSpaceNIBName" bundle:nil];
[self.tableView registerNib:nib forCellReuseIdentifier:CellIdentifier2];
self.contentView.hidden = YES;
[self loadData];
}
Because you have the NIBs registered, dequeueReusableCellWithIdentifier: will always return a cell:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier1 = #"ContentCell";
static NSString *CellIdentifier2 = #"SpaceCell";
// Space Cell
if (indexPath.row % 2 == 1) {
CellSpace *cell = (CellSpace *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
return cell;
}
// Content cell
else {
CellView *cell = (CellView *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
// Configure cell
return cell;
}
}
Last, but not least, make sure to implement the following delegate method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Space cell's height
if (indexPath.row % 2 == 1) {
return 20.0f;
}
// Content cell's height
else {
return 80.0f;
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *returncell;
static NSString *cellIdentifier ;
if(indexPath.section == 0)
{
cellIdentifier = #"cell1";
}
else if (indexPath.section == 1)
{
cellIdentifier = #"cell2";
}
UITableViewCell *myCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
MapTableViewCell *myCustomCell = (MapTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(indexPath.section == 0)
{
if(myCell == nil)
{
myCell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
getLocationBtn = [UIButton buttonWithType:UIButtonTypeCustom];
getLocationBtn.frame = CGRectMake(myCell.frame.origin.x,myCell.frame.origin.y+5 , 200, 30);
[getLocationBtn setTitle:#"your button title" forState:UIControlStateNormal];
[getLocationBtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
[getLocationBtn addTarget:self action:#selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
}
[myCell.contentView addSubview:getLocationBtn];
returncell = myCell;
}
else if (indexPath.section == 1)
{
if (myCustomCell == nil)
{
myCustomCell = [[MapTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
myCustomCell.nearbyLocation.text = #"demo Text";
returncell = myCustomCell;
}
return returncell;
}
//mycustom tablviewcell
import "MapTableViewCell.h"
#implementation MapTableViewCell
#synthesize nearbyLocation;
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self)
{
self.backgroundColor = [UIColor groupTableViewBackgroundColor];
nearbyLocation = [[UILabel alloc]initWithFrame:CGRectMake(10, 5, 200, 30)];
[self addSubview:nearbyLocation];
}
return self;
}
#end
Best way to use number of custom cells with default cell
In addition for the answers provided, I want to emphasize on the Cell Identifier for each different custom cells must be different too.
For example custom cellA with identifier "Cell" and custom cellB with identifier "Cell2".

Resources