This is the type of screen I'm making:
So when the UISwitch state changes it should change the label to ON or OFF. In my cellForRowAtIndexPath I'm calling [cell.mainSwitch addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; and switchChanged is as follow:
-(void) switchChanged:(id)sender {
UISwitch* cellNew = (UISwitch*)sender;
if ([cellNew isOn]) {
cell.funcStatus.text = [funcStatusArr objectAtIndex:0];
} else {
cell.funcStatus.text = [funcStatusArr objectAtIndex:1];
}
}
Now the problem I'm facing is that it is not changing the Label at the specific cell butt all the switches are changing the Label of 4th(last) cell as shown in the figure below.
As you can see that the first label is off but it is changing the label of last row. Any ideas why it is happening or how to tell the functions that this index.row is sending the request.
So u must add tag property to all UISwitch. Fasters way its in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath call
// code
// its good work if u have only 1 section
mySwitch.tag = indexPath.row.
//code
Than fix u're code
-(void) switchChanged:(UISwitch*)switch {
SettingsTableViewCell *selectedCell;
NSIndexPath *selectedIndexPath;
if(switch.tag == 0)
// create selectedIndexPath with correctrly row and section
selectedIndexPath = [NSIndexPath indexPathForRow:'YourRow'inSection:'Your section']
// create cell
selectedCell = [self.tableView cellForIndexPath:selectedIndexPath];
} else if(switch.tag == 1) {
// same logic;
}
// and replace text for selected cell
if ([switch isOn]) {
selectedCell.funcStatus.text = [funcStatusArr objectAtIndex:0];
} else {
selectedCell.funcStatus.text = [funcStatusArr objectAtIndex:1];
}
}
it's must work.
You doing wrong thing.First you need to get cell at specific changed event.
follow this code.
-(void) switchChanged:(id)sender {
UISwitch* switchBtn = (UISwitch*)sender;
//self.tableView is UITableView's outlet named tableView
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
//First detect Tableview's Cell then do the stuff
//CustomCellTableViewCell replace it with you custom cell class
CustomCellTableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if ([switchBtn isOn]) {
cell.funcStatus.text = [funcStatusArr objectAtIndex:0];
} else {
cell.funcStatus.text = [funcStatusArr objectAtIndex:1];
}
[self.tableView reloadRowsAtIndexPaths:[[NSArray alloc] initWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
}
Cheers.
Related
I have a textField on custom cell in a tableView. When one of the cell is selected I am able to disable textField for that particular cell by using set selected method.
(void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if (selected) {
self.accountNameTxtField.enabled = NO;
} else {
self.accountNameTxtField.enabled = YES;
}
}
The requirement is to disable textField for other cells when any one of the cell is selected. Please guide me on this, Thanks.
You have to use instance variable, you could use indexPath.
When user select any cell, set value of that instance variable to selected indexPath.
And reloadTable.
In cellForRowAtIndexPath check if current indexPath is selected indexPath, if yes enable textField else disable it.
Create button on tableview cell and enable or disable textfield on tableview or can apply this logic on tableview didSelectRowAtIndexPath
-(void) btnClick:(id)sender
{
UIButton *btn = (UIButton *)sender;
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:tblView];
NSIndexPath *indexPath = [tblView indexPathForRowAtPoint:buttonPosition];
NSLog(#"table view row is ----%ld",indexPath.row);
if (btn.isSelected == false)
{
[btn setSelected:true];
[selectRow addObject:[NSString stringWithFormat:#"%ld",indexPath.row]];
self.accountNameTxtField.enabled = yes;
//selectRow is NSMutableArray
}
else
{ [btn setSelected:false];
[selectRow removeObject:[NSString stringWithFormat:#"%ld",indexPath.row]];
self.accountNameTxtField.enabled = no;
}
}
[tbleview relaoddata];
if ([selectRow containsObject:[NSString stringWithFormat:#"%ld",indexPath.row]])
{
accountNameTxtField.enabled = yes;
}
else
{
accountNameTxtField.enabled = NO;
}
Use your Data to do this, you must be having some data in for of array containing dictionaries, or class object, I am demonstrating Class Object.
Say you have a Class object DataClass create a BOOL property say textFieldSelected, now follow the steps
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"TableViewCell" forIndexPath:indexPath];
DataClass *object=[self.dataArray objectAtIndex:indexPath.row];
[cell.textField setTag:indexPath.row];
cell.textField.delegate=self;
cell.textField.enabled=object.textFieldSelected;
return cell;
}
Now when you select a row
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
for(DataClass *object in self.dataArray){
object.textFieldSelected=NO;
}
DataClass *object=[self.dataArray objectAtIndex:indexPath.row];
object.textFieldSelected=YES;
[tableView reloadData];
}
Initially you can set textFieldSelected=YES; so that all the textFields are enabled. You can wish to play with object and it will work that way. All the best.
Finally i managed to find the solution with integer cell selection count.
cell selection count gets increased in will select row at index path method and set that value in NsuserDefaults.
selectedIndex++;
NSString *valueToSave = [NSString stringWithFormat:#"%ld",(long)selectedIndex];
[[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:#"SelectedIndexString"];
[[NSUserDefaults standardUserDefaults] synchronize];
cell selection count gets decreased in didDeselectRowAtIndexPath method and set that value in NsuserDefaults.
selectedIndex--;
In my custom table view cell class in textFieldDidBeginEditing method get the stored value from NsUserDefaults and act upon.
NSString *SelectedIndexString = [[NSUserDefaults standardUserDefaults]
stringForKey:#"SelectedIndexString"];
NSLog(#"%ld",(long)SelectedIndexString);
NSInteger SelectedIndexCount = [SelectedIndexString integerValue];
if (SelectedIndexCount) {
self.accountNameTxtField.enabled = NO;
}
else{
self.accountNameTxtField.enabled = YES;
}
Thanks you so much guys. Thanks for your time.
I have a custom UITableView with UITextFields inside. In cellForRow... I made the textFields delegate to self. (In my main VC class.) The way I get the text from the textField is at textFieldDidEndEditing, and I add it to a mutableArray.
I then have different cell ids that get added when a button gets selected:
- (IBAction)addRow:(id)sender
{
NSInteger row = [self.rowArray cound];
[self.rowArray insertObject:#"anotherCell" atIndex:row];
NSIndexPath *indexPath = [NSindexPath indexPathForRow:row inSection:0];
[self.myTableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
(There is a textField in that cellID and I set the delegate to self.)
In textFieldDidEndEditing, I made an NSLog of textField.text, and when that method gets called from a textField that was there initially, it works as expected.
But when textFieldDidEndEditing gets called from the textField that's in the cell of anotherCell (the added cell), then the whole simulator freezes.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellID = [self.rowArray objectAtIndex:[indexPath row]];
customCell *cell = [tableView dequeuereusablecellwithidentifier:cellID forIndexPath:indexPath];
cell.name.delegate = self; // From cell that is initially there
cell.phoneNumber.delegate = self; // From the added cell
return cell;
}
(If this is confusing, or if you need more code, just let me know in the comments. Thanks)
Edit
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if (textField.tag <= 9)
{
NSLog(#"%#", textField.text); // This works
}
UIView *superview = textField.superview;
while (![superview isMemberOfClass:[UITableViewCell class]]) {
superview = superview.superview;
}
CustomCellClass *cell = (CustomCellClass *)superview;
NSIndexPath *indexPath = [self.myTableView indexPathForCell:cell];
if (textField.tag >= 12)
{
if ([self.inputArray count] > indexPath.row) // So I won't get the error message of [__NSArrayM objectAtIndex:]: index 1 beyond bounds for empty array'
{
for (NSUInteger i = [self.inputArray count]; i < indexPath.row; i++) {
[self.inputArray insertObject:#"" atIndex:i];
NSLog(#"%lu", (unsigned long)i);
}
}
NSLog(#"%#", self.inputArray);
}
}
Your code is stuck in an infinite loop here:
while (![superview isMemberOfClass:[UITableViewCell class]]) {
superview = superview.superview;
}
because isMemberOfClass will return true only if the superview class is UITableViewCell, but NOT if it is a subclass of UITableViewCell. If you change isMemberOfClass to isKindOfClass, it should work. Check the Apple docs here.
I'm a newbie with iOS programming language. I try to use table with button in each row.
when i click button in the first cell, it work pretty well.
but when i scroll down, the cell that i don't click also appear click.
I want to show the clicked button in only cell(s) that I clicked?
Code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath{
ClassifyCustomCell * cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if ([[[arrayResult objectAtIndex:indexPath.row] objectForKey:#"COLABO_FLD_SRNO"] isEqualToString:#"I"]) {
cell.editButton.hidden = YES;
cell.folder_name.text = [[arrayResult objectAtIndex:indexPath.row] objectForKey:#"COLABO_FLD_NM"];
}else{
cell.editButton.hidden = NO;
cell.folder_name.text = [[arrayResult objectAtIndex:indexPath.row] objectForKey:#"COLABO_FLD_NM"];
cell.editButton.tag = indexPath.row;
[cell.editButton addTarget:self action:#selector(editButtonAction:) forControlEvents:UIControlEventTouchUpInside];
cell.checkButton.tag = indexPath.row;
[cell.checkButton addTarget:self action:#selector(checkButtonActoin:) forControlEvents:UIControlEventTouchUpInside];
}
return cell;
}
-(void)checkButtonActoin:(UIButton *)sender{
if (sender.selected == YES) {
sender.selected = NO;
}else if(sender.selected == NO){
sender.selected = YES;
}else {
sender.selected = NO;
}
}
UITableView reuse the state of cell's subviews for new cells. To prevent reusing just configure your subviews explisitly in tableView:cellForRowAtIndexPath:. In your case you need to set selected property of your button to YES, if it was selected, and to NO, if it was not selected.
Add NSMutableArray property to your view controller:
#property (strong, nonatomic) NSMutableArray *arrayForSelectedIndexPaths;
Change your tap method:
-(void)checkButtonAction:(UIButton *)sender{
UITableViewCell *cell = (UITableViewCell *) sender.superview.superview...; //find appropriate number of superviews to get your cell
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
if (sender.selected) {
sender.selected = NO;
[self.arrayForSelectedIndexPaths removeObject:indexPath];
}else {
sender.selected = YES;
[self.arrayForSelectedIndexPaths addObject:indexPath];
}
}
Then in tableView:cellForRowAtIndexPath: add this line:
cell.checkButton.selected = [self.arrayForSelectedIndexPaths containsObject:indexPath];
I have a rate button. Upon clicking on that button a view containing 5 stars opens. But when I click on rate button of particular cell, particular view opens but some views of other cells also get opens. I want the view containing 5 stars of that particular view only to get opened.
I am attaching the code of that view.
cv = [[ASStarRatingView alloc]initWithFrame:CGRectMake(190, y-5, 140, 30)]; //creat an instance of your custom view
cv.tag = indexPath.row ;
if([delegate.constants.snsrate[indexPath.row] isEqualToString: #"0"])
{
cv.hidden=TRUE;
}
else
{
cv.hidden=FALSE;
}
delegate.constants.selected=1;
[cell addSubview:cv];
And my code to close and open the view.
-(void)Rate_Comment:(UIButton *)sender
{
UIButton *b = (UIButton *)sender;
NSInteger row = b.tag ;
for(int i=0;i<[delegate.constants.snsrate count];i++)
delegate.constants.snsrate[i]= #"0";
delegate.constants.buttontag = row;
UITableViewCell *buttonCell = (UITableViewCell *)[b superview];
UITableView* table = (UITableView *)[buttonCell superview];
NSIndexPath* pathOfTheCell = [table indexPathForCell:buttonCell];
delegate.constants.snsIndexPath = pathOfTheCell;
if(![delegate.constants.user_id isEqualToString:[delegate.constants.snsCreatedBy objectAtIndex:row]])
{
if([[delegate.constants.snstotalrating_count objectAtIndex:row] isEqualToString:#"0"])
{
if(cv.hidden)
{
delegate.constants.snsrate[row]= #"1";
cv.hidden=FALSE;
}
else{
delegate.constants.snsrate[row]= #"0";
cv.hidden=TRUE;
}
[streamTable reloadRowsAtIndexPaths:#[pathOfTheCell] withRowAnimation:UITableViewRowAnimationNone];
}else
{
if(cv.hidden==FALSE)
cv.hidden=TRUE;
}
}
}
I am new to IOS. Please if anyone can help it will be much appreciated.
Thank you in advance.
I assume every cell has a "rate" button and a target method, like this:
// --------------------------------------------------------------------
// Sorry, I'm typing from memory, these code might not be 100% correct
// --------------------------------------------------------------------
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cell";
MyCustomCell *cell = [tableView dequeueReusableCellForIdentifier:cellID];
if(cell == nil)
{
cell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
// --------------------------------------------------------
// Add the method to execute when tapping on a button
// --------------------------------------------------------
[cell.btnRate addTarget:self action:#selector(showRateControl:) forControlEvent:UIControlEventTouchUpInside];
}
// self.selectedRow should init with -1, since we don't want to show stars
// for the first row if self.selectedRow defaults to 0
if(self.selectedRow == indexPath.row)
{
cell.starsView.alpha = 1;
cell.btnRate.alpha = 0;
}
else
{
cell.starsView.alpha = 0;
cell.btnRate.alpha = 1;
}
return cell;
}
-(void)showRateControl:(id)sender
{
UIButton *rateButton = (UIButton *)sender;
// finding the row which the rate button was tapped
CGPoint rootPoint = [rateButton convertPoint:CGPointZero inView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rootPoint];
// ------------------------------------------------------------
// here we record the row which the rate button was tapped
// in a property we declared in the .h file (see below)
// ------------------------------------------------------------
self.selectedRow = indexPath.row;
// refresh just the selected row (you could alternatively use self.tableView reloadData)
[self.tableView reloadRowsAtIndexPath:#[indexPath]];
}
In your header file, you can declare your selectedRow property like this:
...
class MyViewController: UIViewController
{
}
#property (nonatomic, assign) NSInteger selectedRow;
#end
In your implementation file's viewDidLoad, don't forget to initialise self.selectedRow to -1:
-(void)viewDidLoad
{
[super viewDidLoad];
...
self.selectedRow = -1;
}
See if that helps.
I have an array of user displayed in a table view when pushing the send button the cell dosen't selected right object. It can be quit random:). How do i make send the object displayed on the selected cell?
This is how i send my message
- (void)sendMessage:(id)sender {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
PFObject *object = [self.objects objectAtIndex:indexPath.row];
self.SendToUsername = [object objectForKey:#"username"];
self.SendToName = [object objectForKey:#"name"];
}
And this is my cell, where the send button is located.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = #"LampCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
UIButton *sendbutton = (UIButton*) [cell viewWithTag:105];
[sendbutton addTarget:self action:#selector(sendMessage:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
It is quite easy. Tableview itself provide method.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
variable=[array objectAtIndex:indexPath.row];
}
In "Variable" you have value which is selected. If your array is accessible in whole controller then you can save "indexPath.row" and use on click event of send button to fetch selected record.
tableView indexPathForSelectedCell will not give you the index path you are expecting in the action method of a button that is in a cell. The cell wasn't selected - you touched the button.
To get the index path of the row for that button, there are a couple of different methods.
My preferred method is to traverse the view hierarchy to find the cell that contains the button, and use that to get the index path. See this question for more info:
Button in custom cell in dynamic table: how to know which row in action method?
My answer from this question is as follows. You could add these two methods to a category on UITableViewController, or you could just add them to your view controller, if you like.
- (NSIndexPath *)indexPathForCellSubview:(UIView *)subview
{
if (subview) {
UITableViewCell *cell = [self tableViewCellForCellSubview:subview];
return [self.tableView indexPathForCell:cell];
}
return nil;
}
- (UITableViewCell *)tableViewCellForCellSubview:(UIView *)subview
{
if (subview) {
UIView *superView = subview.superview;
while (true) {
if (superView) {
if ([superView isKindOfClass:[UITableViewCell class]]) {
return (UITableViewCell *)superView;
}
superView = [superView superview];
} else {
return nil;
}
}
} else {
return nil;
}
}
You could then get the index path in your button action method like so:
NSIndexPath *indexPath = [self indexPathForCellSubview:sender];
You don't need to set the tag for buttons to get the indexpath. You can simply get it using this piece of code:
- (void)sendMessage:(id)sender {
UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
NSIndexPath *clickedButtonIndexPath = [self.tableView indexPathForCell:clickedCell];
PFObject *object = [self.objects objectAtIndex:indexPath.row];
self.SendToUsername = [object objectForKey:#"username"];
self.SendToName = [object objectForKey:#"name"];
}