Loop through textFields ONLY, in UITableView - ios

I have a custom UITableView. I have textFields and other objects in the tableView. I'm trying to loop through all the textFields only.
Here is my Code:
for (int i = 0; i < [self.rowArray count]; i++) {
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
for (UITextField *textField in [cell.contentView subviews]) {
NSLog(#"%#", textField.text);
}
}
The app crashes with the following error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIImageView text]: unrecognized selector sent to instance 0x7f89eb57b000'
The problem is obviously that it cannot do an NSLog of an image. But it wasn't supposed to. It was just supposed to go through the textFields?

You can test the class of the subviews using isKindOfClass::
for (int i = 0; i < [self.rowArray count]; i++) {
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
for (id subview in [cell.contentView subviews]) {
if ([subview isKindOfClass:[UITextField class]]) {
UITextField *textField = (UITextField *)subview;
NSLog(#"%#", textField.text);
}
}
}
NOTE You should not be interrogating the tableview in this way as it's the V bit of MVC and you already have access to all the data within the M bit...

Try this:
Provide a unique tag to the textField when u add them as subview to the cells. For Example: Take a constant value
#define kTagTextField 1211
Now in cellForRowAtIndexPath: do this
[textField setTag:(kTagTextField+indexPath.row)];
and where u want to have the text do this
for (int i = 0; i < [self.rowArray count]; i++) {
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
if([cell viewWithTag:(kTagTextField+i)]) {
UITextField *txtField = [cell viewWithTag:(kTagTextField+i)];
NSLog(#"%#", textField.text);
}
}

Related

When textFieldDidEndEditing gets called, the app freezes

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.

Find indexPath of cell by label

I have table with cells; each cell contain label with phone number. When i tap on the label, UIMenuController appears.
Is there a main way to find indexPath of cell, which contain selected label? (didSelectRowAtIndexPath: should not be called)
I can imagine many dirty hacks, but i looking for a main/good solution.
upd
I have reference to selected label.
Edit:
This is a better way.
- (IBAction)someMethod:(id)sender {
CGPoint hitPoint = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *hitIndex = [self.tableView indexPathForRowAtPoint:hitPoint];
}
From your label, search for the cell object in the label's hierarchy:
-(UITableViewCell*) cellContainingView:(UIView*)view
{
UIView* currentView = view;
while (currentView)
{
if ([currentView isKindOfClass:[UITableViewCell class]])
{
return (UITableViewCell*)currentView;
}
currentView = currentView.superview;
}
return nil;
}
Once you have the cell, call [tableView indexPathForCell:cell]
The use of this method instead of hard coding view.superview.superview makes your code stronger because it handle possible changes in cell's view hierarchy through system's versions.
You could go:
NSMutableArray *cells = [[NSMutableArray alloc] init];
for (NSInteger j = 0; j < [tableView numberOfSections]; ++j)
{
for (NSInteger i = 0; i < [tableView numberOfRowsInSection:j]; ++i)
{
[cells addObject:[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]]];
}
}
for (UITableViewCell *cell in cells){
for (UILabel *label in cell.subviews){
if (label == yourLabel)
indexPath = [tableView indexPathForCell: cell];
}
}

scroll tableview programatically with custom cell

EDITED CODE..
Hello frds, i have one buttom in UIScrollview when i clicked on that button then i get btn.tag , so after that i want to scroll UITableView programatically.
Here is my Code.
//-- Custom Scrollview--//
- (void)loadscrollViews
{
int a =[DBConnection rowCountForTable:#"DD_Pic_Tags_Comments" where:[NSString stringWithFormat:#"img_Moment_id=%#",STR_Select_moment_id_for_timelinepage2]];
numofimageinscrollview=a;
int x=0;
for (int i = 0; i < a; i++)
{
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
btn.frame=CGRectMake(x, 0,scrollView.frame.size.height,scrollView.frame.size.height);
btn.tag=i;
UIImage *image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/%#.jpg",Pathforimage,[[Array_result objectAtIndex:i] objectForKey:#"img_File_Name"]]];
[btn setImage:image forState:UIControlStateNormal];
[btn addTarget:self action:#selector(imageClick:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:btn];
scrollView.contentSize=CGSizeMake((i+2)*scrollView.frame.size.height,scrollView.frame.size.height);
x+=scrollView.frame.size.height+5;
}
}
-(void)imageClick:(id)sender
{
UIButton *btn=(UIButton *)sender; //UIScrollView Button
int count = (int)btn.tag;
NSLog(#"click on small image in Scrollview>> count = %d",count);
NSIndexPath *indexpath=[NSIndexPath indexPathForRow:count inSection:0]; //Set Count For RoW
NSLog(#"%d %d",indexpath.row,indexpath.section);
[self.Table reloadData];
[self.Table scrollToRowAtIndexPath:indexpath
atScrollPosition:UITableViewScrollPositionTop
animated:NO];
}
Get Error like,
2014-08-25 16:34:27.757 Omoment[5163:60b] click on small image in Scrollview>> count = 2
2014-08-25 16:34:27.758 Omoment[5163:60b] 2 0
2014-08-25 16:34:27.761 Omoment[5163:60b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '-[UITableView _contentOffsetForScrollingToRowAtIndexPath:atScrollPosition:]: row (2) beyond bounds (0) for section (0).'
*** First throw call stack:
libc++abi.dylib: terminating with uncaught exception of type NSException
but,
app crash , but when i set NSIndexPath *indexpath=[NSIndexPath indexPathForRow:1 inSection:0];
//at that time app does not crash, & there is no output in uitableview, & also scrollview did not scroll also..
I think you have not defined the tag for that image in cellforrowatindexpath. I have used a button instead of image.I hope it works for u.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CustomCell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:simpleTableIdentifier owner:self options:nil] objectAtIndex:0];
}
cell.txtlabel.text = [NSString stringWithFormat:#"Hello %d", indexPath.row];
[cell.btnnn addTarget:self action:#selector(btnPressed:) forControlEvents:UIControlEventTouchUpInside];
cell.btnnn.tag=indexPath.row;
return cell;
}
-(void)btnPressed:(id)sender{
UIButton *btn=(UIButton *)sender; //UIScrollView Button
int count = (int)btn.tag;
NSLog(#"click on small image in Scrollview>> count = %d",count);
NSIndexPath *indexpath=[NSIndexPath indexPathForRow:count inSection:0]; //Set Count For RoW
NSLog(#"%d %d",indexpath.row,indexpath.section);
// [self.tbl reloadData];
[self.tbl scrollToRowAtIndexPath:indexpath
atScrollPosition:UITableViewScrollPositionTop
animated:NO];
}
You need to scroll the Scrollview.
For this first calculate the CGPoint up to which you need to scroll.
Then use this:
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
So your final code would be something like this:
-(void)btnPressed:(id)sender{
UIButton *btn=(UIButton *)sender; //UIScrollView Button
CGFloat y_point = btn.center.y; // Adjust the y point according to you
CGPoint thePoint = CGPointMake(0, y_point); // Assuming its a vertical scroll
[self.myScroll setContentOffset:thePoint animated:YES];
}

Make Change in TableViewCell

I'm working on the TableView, and I have used the label on the TableViewCell and on the button click I want to hide the label from all cells in my table,
In the label I have set the tag:
label.tag = indexPath.row+1;
And on the button click I am using the code like this:
for (int i = 0; i < Array.count; i++)
{
[[self.view viewWithTag:i+1] setHidden:YES];
}
But from my code the label is hiding only from the last cell not all the others.
You can simply do this with another way.
First you need to declare a BOOL in your class
#property(assign,nonatomic) BOOL hideLabels;
Next in your button action handler method, set this YES
In your cellForRowAtIndexPath, check whether hideLabels is YES, if yes, the hide labels using code.
cell.yourLabel.hidden = hideLabels;
Now reload the table after setting hideLabels as YES
[self.tableView reloadData];
for(id object in tableView.subviews)
{
if([object isKindOfClass:[UILabel class]])
{
UILabel *label = (UILabel *) object;
[[label setHidden:YES];
}
}
In your ViewController.h
BOOL isLabelHidden;
in ViewController.m
- (void)viewDidLoad
{
isLabelHidden = FALSE;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TableCell";
UILabel *lbl;
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = nil;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if(isLabelHidden)
[lbl setHidden:YES];
else
[lbl setHidden:NO];
}
in you button clicked method
- (void)buttonClicked
{
isLabelHidden = TRUE;
[tableView reloadData];
}
You should first get the reference to the UITableViewCell and then you can remove the labels in them.
First of all get the reference to all the cells in your tableview as follows:
NSMutableArray *cells = [[NSMutableArray alloc] init];
for (NSInteger j = 0; j < [tableView numberOfSections]; ++j)
{
for (NSInteger i = 0; i < [tableView numberOfRowsInSection:j]; ++i)
{
[cells addObject:[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]]];
}
}
And now iterate through those cells in cells Array to hide the label view,
for (int i = 0; i < cells.count; i++)
{
[[[cells objectAtIndex:i] viewWithTag:i+1] setHidden:YES];
}
Source:How can I loop through UITableView's cells?

how to find button in cell subview

Good day!
Here is a problem: i've added a button in cell in my UITableView programmatically like this:
UIButton *button = [[UIButton alloc] initWithFrame:buttonFrame];
[button setImage:[UIImage imageNamed:#"Button_off_weather"] forState:UIControlStateNormal];
button.tag = indexPath.row;
[button addTarget:self action:#selector(buttonCityTapped:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview: button];
it works fine.
then i want to find it in table and switch off like this:
NSMutableArray *cells = [[NSMutableArray alloc] init];
for (NSInteger j = 0; j < [_tableView numberOfSections]; ++j)
{
for (NSInteger i = 0; i < [_tableView numberOfRowsInSection:j]; ++i)
{
[cells addObject:[_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]]];
for (UITableViewCell *cell in cells)
{
for (id theView in cell.subviews) {
if ([theView isKindOfClass:[UIButton class]]) {
[theView performSelector:#selector(buttonOff:)];
}
}
}
}
}
this does not work. is there any ideas?
Create a custom cell subclass with an #property making the button available. This is the correct approach to take.
Your current approach is currently and will in the future be error prone. Try not to rely on code which traverses view hierarchies, particularly if you don't have control over some parts of the view hierarchy (like the cell subviews).
use enumeration with [cell.contentView subviews]
for(UIView *view in [cell.contentView subviews])
{
if([view isKindOfClass:[UIButton class]])
{
[theView performSelector:#selector(buttonOff:)];
}
}
Check This: Works fine for me.
int sections = [self.tableView numberOfSections];
for (int i=0; i<sections; i++) {
//For the Custom cell
NSIndexPath *myIP = [NSIndexPath indexPathForRow:0 inSection:i] ;
CellStar *cell =(CellStar *) [self.tableView cellForRowAtIndexPath:myIP];
UITextView *txtVi ;
NSArray *subviews = cell.contentView.subviews;
for(id element in subviews) {
if ([element isKindOfClass:[UITextView class]]){
NSLog(#"element is a UItextView\n");
txtVi = (UITextView *)element;
}
if([element isKindOfClass:[UIButton class]]){
UIButton *btn = (UIButton *) element;
NSLog(#"element is UIButton\n");
}
}
//[self.tableView reloadData];
}

Resources