when I create a custom UITableviewCell I set cell.selected = YES in the UITableView delegate method tableview:cellForRowAtIndexPath, but it doesn't work.
However, when I call [tableView selectRowAtindexPath:] after [tableview reloadData], there is no problem. I am confused
Here is some code source:
-(void)setModel:(GAInterestSetModel *)model
{
_model = model;
if (model.iconURL && model.iconURL.length > 1) {
[iconView setImageWithURL:[NSURL URLWithString:model.iconURL]];
}
if (model.title && model.title.length > 1) {
titleLabel.text = model.title;
}
if (model.memberCounts) {
membersLabel.text = [NSString stringWithFormat:#"成员:%d",model.memberCounts];
}
self.selected = model.defaultChoosed;
}
instead method:
[modelsArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
tempModel = (GAInterestSetModel *)obj;
if (tempModel.defaultChoosed) {
[rootTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:idx inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}];
The selection is not a property of the cell. Calling .selected = YES does absolutely nothing because the table doesn't know about the selection.
You have to use [table selectRowAtIndexPath:...] otherwise it won't work.
Another possibility is to ignore the default selection and implement your own selection mechanism.
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.
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.
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 have a uicollectionview hosting a number of cells, each cell has a title on it.
the same collectionview can have multiple cells that have the same title.
I need to grammatically scroll the collectionview to the first occurrence of a cell which has title = user selection.
How can I achieve that?
Loop through you data source and find the first object and call then call collection views scrolltoIndexPath method.
__block NSIndexPath* indexPath = nil;
[yourDataSource enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isEqualToString:title]) {
indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
*stop = YES;
}
}];
if (indexPath) {
//set the scroll position accordingly
[collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
}
I have a custom grouped TableView with 5 sections and in total with 50 custom cells of type:
Label | XXX
where XXX can be UITextField, UITextView, UIButton, UILabel. Cells have mixed order in tableView.
To navigate through textFields & textViews i added Next/Prev buttons on my keyboard.
The problem is the when i select txtField and click Next or Prev button, the table scrolls to the needed cell position, but txtField doesn't get the cursor. In order to get the cell with textField/textView i use:
nextCell = [self tableView:_myTableView
cellForRowAtIndexPath:[NSIndexPath indexPathForRow:curRow inSection:curSec]];
I need to search through all cells in tableView, not only through the visible ones.
As i tested, the problem is in this line of code, because if i call:
nextCell = [_myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:curRow inSection:curSec]];
and the cell is visible, then the txtField gets cursor. However, if i need to jump from cell (section = 1, row = 6) to cell (section =0, row = 3) which is not visible, i get nil.
My full code of button function:
-(void) previousTextField:(id)sender
{
int curTagInd = _editingTextElement.tag;
NSIndexPath *curInd = [self getRowIndexOf:_editingTextElement];
int curSec = curInd.section;
int curRow = curInd.row;
id nextView = nil;
UITableViewCell *nextCell = nil;
do {
curRow--;
if (curRow >=0) {
nextCell = [self tableView:_myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:curRow inSection:curSec]];//[_myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:--curRow inSection:curInd.section]];
curTagInd--;
if ([nextCell isKindOfClass:[CustomCell class]] || [nextCell isKindOfClass:[CustomLongTextCell class]]) {
do {
nextView = [nextCell viewWithTag:curTagInd];
if ([nextView isEnabled]) {
nextCell = nil;
_editingIndexPath = [NSIndexPath indexPathForRow:curRow inSection:curSec];
break;
}else{
break;
}
} while (nextView != nil && ((![nextView isKindOfClass:[UITextField class]] && ![nextView isKindOfClass:[UITextView class]]) || ![nextView isEnabled]));
}
}
else if(curSec > 0){ //got to previous section
curSec--;
curRow = [self getNumberOfRowsInSection:curSec];
curTagInd = [self getNumberOfRowsInSection:curSec]+1;
}
else{
nextCell = nil;
}
} while (nextCell != nil);
if (nextView != nil) {
[self.myTableView scrollToRowAtIndexPath:_editingIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
UITextField *textField = (UITextField *)nextView;
[textField becomeFirstResponder];
}
}
Using this code i get inside method textFieldShouldBeginEditing:, but not in textFieldDidBeginEditing:
SOLUTION:
The problem was that the table began scrolling only after the function previousTextField: was finished, and thus, [textField becomeFirstResponder]; was called before the table was scrolled to the needed position. Due to the fact that needed cell is still not visible on the screen, delegate methods didn't call.
To avoid this, i added timer after table-scrolling line:
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 0.2
target: self
selector:#selector(doneScrolling)
userInfo: nil repeats:NO];
and defined doneScrolling like:
-(void)doneScrolling
{
NSLog(#"done scrolling");
[self tableView:self.myTableView didSelectRowAtIndexPath:self.editingIndexPath];
}
where:
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIView *nextView = [cell viewWithTag:indexPath.row+1];
if ([nextView isKindOfClass:[UITextView class]] || [nextView isKindOfClass:[UITextField class]]) {
if ([nextView isEnabled]) {
UITextField *textField = (UITextField *)nextView;
[textField becomeFirstResponder];
}
}
}