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];
}
Related
I have a UIButton click sender as below:-
-(IBAction)clipButtonClick:(UIButton *)sender
{
sender.selected = ! sender.selected;
if (sender.selected)
{
[btnClipCategory setImage:[UIImage imageNamed:#"imgClip_HL"] forState:UIControlStateSelected];
NSMutableArray* indexArray = [NSMutableArray array];
for (NSInteger i = 0; i < self.arySubCategory.count; i++)
{
[aryCheckCategoryList replaceObjectAtIndex:i withObject:#"YES"];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[indexArray addObject:indexPath];
dispatch_async(dispatch_get_main_queue(), ^{
[self.rightTableView reloadData];
});
}
}
else
{
[btnClipCategory setImage:[UIImage imageNamed:#"imgClip"] forState:UIControlStateNormal];
NSMutableArray* indexArray = [NSMutableArray array];
for (NSInteger i = 0; i < self.arySubCategory.count; i++)
{
[aryCheckCategoryList replaceObjectAtIndex:i withObject:#"NO"];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[indexArray addObject:indexPath];
dispatch_async(dispatch_get_main_queue(), ^{
[self.rightTableView reloadData];
});
}
}
}
When I clicked on the button, sender will always hit on selected option.
If i change the sender to code to sample code as below, my apps will working properly as expected. Any idea? Please help. Thank you.
-(IBAction)clipButtonClick:(UIButton *)sender
{
sender.selected = ! sender.selected;
if (sender.selected)
{
[btnClipCategory setImage:[UIImage imageNamed:#"imgClip_HL"] forState:UIControlStateSelected];
NSLog(#"Selected. Will Hit here");
}
else
{
[btnClipCategory setImage:[UIImage imageNamed:#"imgClip"] forState:UIControlStateNormal];
NSLog(#"Non Selected. Will Hit here");
}
}
Edited
I put my button under willDisplayHeaderView.
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section{
UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view;
btnClipCategory = [UIButton buttonWithType:UIButtonTypeCustom];
[btnClipCategory setFrame:CGRectMake(header.frame.size.width - 45, header.frame.size.height * 0.2, ScreenW * 0.1, ScreenW * 0.1)];
[btnClipCategory addTarget:self action:#selector(clipButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[header addSubview:btnClipCategory];
}
When you call [self.rightTableView reloadData], all the content of the table view including sections headers gets reloaded, and tableView:willDisplayHeaderView:forSection: gets called for each visible section header. So your bntClipCategory gets recreated with default value of isSelected each time click action fires.
You don't reload rightTableView in your working code sample, that's why it works.
You should reconsider you approach. One of the options is to save isSelected state of buttons for each section in array and update btnClipCategory.isSelected accordingly before adding it to header view.
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);
}
}
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];
}
}
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?
I want to access a button of a section header when user clicks on row in tableview. I can get clicked row number and that particular section by using NSIndexpath (i.e. section 1 - row 0 etc.), but could not retrieve button in the section header. I've tried using isKindOfClass by iterate through tableview, but did not work.
MainTableViewCell *clickedResourceCell = (MainTableViewCell*)btn.superview.superview;
clickedResourceCell.customThresholdBar.value = slider.value/100;
NSIndexPath *indexpath = [self.tableView indexPathForCell:clickedResourceCell];
[btn setTitle:[NSString stringWithFormat:#"%i%#", [[NSNumber numberWithFloat:[(UISlider *)sender value]] intValue], #"%"] forState:UIControlStateNormal];
self.sliderValueLabel.text = [NSString stringWithFormat:#"%i%#", [[NSNumber numberWithFloat:[(UISlider *)sender value]] intValue], #"%"];
I've got row's button updated.Now want to update section.I've tried like this!
for(UIView *view in [self.tableView subviews])
{
if([view isKindOfClass:[UIButton class]])
{
UIButton *bttn = (UIButton *)view;
if (bttn.titleLabel.tag == 7) {
if (bttn.tag == indexpath.section) {
NSLog(#"FOUND");
[bttn setTitle:[NSString stringWithFormat:#"%i%#", completedAmount/i, #"%"] forState:UIControlStateNormal];
}
}
}
}
Do it this way:
UIView *sectionHeader = [tableView headerViewForSection:indexPath.section];
UIButton *button = (UIButton*)[sectionHeader viewWithTag:<button's tag>];
whenever you have the indexpath of the row.
Good Luck!