Setting button tag with variable - iphone

I have a json array with certain objects : first name , last name, unique id. I am able to parse them and save them in dictionary and also check them for NULL conditions.
I have created a table in which i am able to display the names. Also, i have one button in each row as well and i have tagged them. What i want is that when i click the button, i am able to see the unique id fetched from server in my console. I need to pass this unique id to next view as using this unique id would help me to display view corresponding to that id on server.
Click here to see what I have done so far
I have made some changes by adding this to my viewDidLoad method:
for(NSDictionary *items in infos)
{
....
....
for(int i =0; i < len; i++)
{
...
...
...
for(NSDictionary *newItems in infoArray)
{
...
...
NSString *folks_IdRcv = [[items objectForKey:strr]objectForKey:#"folks_id"];
NSLog(#"FolksID = %#", folks_IdRcv);
NSString *folksIDString = [NSString stringWithFormat:#"%#", folks_IdRcv, nil];
NSLog(#"folkid_display=%#", folksIDString);
if((fName && lName && email_Id && number_id) && displayName && folksIDString != NULL)
{
...
...
[folksIDArray insertObject:folksIDString atIndex:ii];
NSLog(#"FolksID String Name = %#", [folksIDArray objectAtIndex:(ii)]);
ii++;
}
}
}
}
NSMutableArray *nArray = [[NSMutableArray alloc]initWithCapacity:len];
for(int j =0; j<len ;j++)
{
...
...
[nArray addObject:[folksIDArray objectAtIndex:j]];
NSLog(#"FID Element=%#", nArray);
}
self.infos = mArray;
[super viewDidLoad];
}
And for this particular code, i am getting the following response:
FID Element=(
400386528950544,
162622322666106,
643171434889706
)
Now, I have a table view in which i have one button for each row and i am able to display the first and last names in each row. What I want now is that whenever I click the button, the unique id for that particular name should be saved in the tag so that i can send that id to the server on button click action.
Please help me out.

Here, I assume that you can make array of unique id array and this array should be declare in .h file or should be class member. Than use following code.
-(IBAction)buttonClicked1:(id *)sender{
NSString *UIDString = [uidarray objectAtIndex:[sender tag]]; // uidarray is unique id array
NSLog(#"uid for particular button=%#", UIDString);// this will give you kid for button that you tapped or clicked.
}

I have one Idea for your requirement...
In TableView Delegate Method.....
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
.............your another code........
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect frame = CGRectMake(0.0, 0.0, 14, 14);
button.frame = frame; // match the button's size with the image size
[button setBackgroundImage:image forState:UIControlStateNormal];
// set the button's target to this table view controller so we can interpret touch events and map that to a NSIndexSet
[button addTarget:self action:#selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor clearColor];
cell.accessoryView = button;
return cell;
}
after paste this method ...
- (void)checkButtonTapped:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:Yourtableview];
NSIndexPath *indexPath = [Yourtableview indexPathForRowAtPoint: currentTouchPosition];
if (indexPath != nil)
{
[self tableView: Yourtableview accessoryButtonTappedForRowWithIndexPath: indexPath];
}
}
and also in accessoryButtonTappedForRowWithIndexPath Delegate method of tableview....
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
NSMutableDictionary *item = [self.arrTypes objectAtIndex:indexPath.row];//sel.arrTypes is Array Data..use your Data here and
....... do somthing here which you want ......
}

Tag is one way another way is sender superview. Refer below code (Not require to set tag)
- (IBAction)clickedButton:(id)sender
{
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview;
UITableView *tableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
NSString* id = [Array objectAtIndex:indexPath.row];
}
and if you are using tag then make sure tag must be unique.

use this UIButton* btn.....
btn.tag.
and when button pressed
UIButton *button = (UIButton*)sender;
thetatosendserver = button.tag

Related

How do I retrieve UITableView row number of a UISwitch?

I have tried several approaches posted here, but I cannot get my table full of switches to return an index value for the cell of the changed switch. I am creating the view containing the table programmatically (no xib).
TableSandboxAppDelegate.m I instantiate the view controller in didFinishLaunchingWithOptions: with:
...
TableSandboxViewController *sandboxViewController = [[TableSandboxViewController alloc]
init];
[[self window] setRootViewController:sandboxViewController];
...
TableViewController.h file reads:
#interface TableSandboxViewController : UITableViewController
{
NSMutableArray *_questionOrder;
NSMutableArray *switchStates;
}
#end
TableViewController.m cellForRowAtIndexPath: reads:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
UISwitch *theSwitch = nil;
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"MainCell"];
theSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
theSwitch.tag = 100;
[theSwitch addTarget:self action:#selector(switchChanged:)
forControlEvents:UIControlEventValueChanged];
[cell.contentView addSubview:theSwitch];
} else {
theSwitch = [cell.contentView viewWithTag:100];
}
if ([[switchStates objectAtIndex:indexPath.row] isEqualToString:#"ON"]) {
theSwitch.on = YES;
} else {
theSwitch.on = NO;
}
return cell;
TableViewController.m -(IBAction)switchChanged:(UISwitch *)sender reads:
UITableViewCell *theParentCell = [[sender superview] superview];
NSIndexPath *indexPathOfSwitch = [self.tableView indexPathForCell:theParentCell];
NSLog(#"Switch changed at index: %d", indexPathOfSwitch.row);
My log result is always "Switch changed at index: 0". I feel like the problem is in that CGPoint line where I've tried combinations of replacements for "sender" ([sender superview], [[sender superview]superview], etc). I don't feel like that line is pointing to the view that displays the table.
What am I doing wrong?
Note added 10/9, 9:15 EDT: my goal is to be able to handle about 100 yes/no questions in the table, so reuse is a key. I want to scroll and have the table the state of each switch, as well as be able to retrieve them when leaving the view.
Tags is an okay solution, but a little clumsy because the cells - and therefore their subviews - are continually being reused, changing their rows - and therefore the tags they need.
Instead, I generally keep one of these around:
- (NSIndexPath *)indexPathWithSubview:(UIView *)subview {
while (![subview isKindOfClass:[UITableViewCell self]] && subview) {
subview = subview.superview;
}
return [self.tableView indexPathForCell:(UITableViewCell *)subview];
}
Then when I get an IBAction:
- (IBAction)someSubviewAction:(id)sender {
NSIndexPath *indexPath = [self indexPathWithSubview:(UIView *)sender];
// carry on from here
}
You may set switch view tag to row index. Instead of theSwitch.tag = 100;
do
-(UITableViewCell*)tableView:table cellForRowAtIndexPath:indexPth
{
UISwitch *theSwitch = nil;
if (cell == nil) {
...
// as per your example
[cell.contentView addSubview:theSwitch];
} else {
theSwitch = subviewWithClass(cell.contentView, [UISwitch class]);
}
theSwitch.tag = indexPath.row;
...
}
Add this helper function to replace viewWithTag: call
UIView *subviewWithClass(UIView *contentview, Class klass)
{
for (UIView *view in contentview.subviews)
if ([view isKindOfClass:klass])
return view;
return nil;
}
Then retrieve tag, that is a row index now, in your switchChanged function
-(IBAction)switchChanged:(UISwitch *)sender {
NSLog(#"Selected Switch - %d", sender.tag);
...
}
If you use something block-based (like https://github.com/brightsoftdev/iOS-Block-Based-Bindings/blob/master/UISwitch%2BBindings.m), you don't need to worry about getting the row, because you can reference the indexPath that is passed into tableView:cellForRowAtIndexPath: in your block.
Similar to #danh, I've come up with this solution using an extention which I've used multiple times.
#interface UIView (Find)
- (id)findSuperviewOfClass:(Class)class;
- (NSIndexPath *)findIndexPath;
#end
#implementation UIView (Find)
- (id)findSuperviewOfClass:(Class)class
{
return [self isKindOfClass:class] ? self : [self.superview findSuperviewOfClass:class];
}
- (NSIndexPath *)findIndexPath
{
UITableView *tableView = [self findSuperviewOfClass:[UITableView class]];
return [tableView indexPathForCell:[self findSuperviewOfClass:[UITableViewCell class]]];
}
#end
for iOS6+ you could maintain a NSMutableArray queuedSwitches
in -tableView:cellForrowAtIndexPath: you would take a switch, if not empty and places it on the custom cell and assign it to a property. If empty you create a new one.
in -tableView:didEndDisplayingCell:forRowAtIndexPath: you would add it to quededSwitches and remove it from it cell.
This will just allocate enough switches for visible cells and reuse them.
the switches are all wired up to one action.
-(void)switchAction:(UISwitch *)switch
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:[switch superView]];
//…
}
You could create a subclass of UISwitch and add an indexPath property, then just set the indexPath in cellForRowAtIndexPath:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
SwitchCell *returnCell = [tableView dequeueReusableCellWithIdentifier:#"SwitchCell" forIndexPath:indexPath];
returnCell.switch.indexPath = indexPath;
return returnCell;
}

Getting data of a particular row in a table view controller corresponding to the click of a button

I am new to IOS development. I am working on an app in which I have few rows and a button in front of each row. In the cellForRowAtIndexPath I have created a function called buttonPressed() and in that function I want to get the data only corresponding to the button I click. Can you help me with this?
Here's what I am doing.
-(void) buttonPressed: (id) sender withEvent: (UIEvent *) event
{
UITouch *touch= [[event allTouched] anyObject];
CGPoint location = [touch locationInView: self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
trackedUser = [searchResult obectAtIndex:indexPath.row];
}
trackedUser is the object of a class which contains the details of a user like his name, id etc. And SearchResult is an array which displays the list of usernames (on searching in the search bar) in the table view controller.
Modify your cellForRowAtIndexPath-Adding button to cell code like below
UIButton *yourButton = [[UIButton alloc] initWithtarget:..] //creating UIButton with frame and target method
yourButton.tag= indexPath.row;
[cell addSubview:yourButton];
[yourButton release];
Then modify your buttonPressed method as below
-(void) buttonPressed: (id) sender withEvent: (UIEvent *) event
{
  UIButton *myBtn = (UIButton *)sender;
       trackedUser = [searchResult obectAtIndex:myBtn.tag];
}
//Instead of using Touch Handlers, you can make it more simple!!
In cellForRowAtIndexPath datasource add tags to UIButton like yourButton.tag = indexPath.row;
-(void) buttonPressed: (UIButton *) sender
{
NSLog(#"The row %d button was pressed",sender.tag);
//To get data, simply pass sender.tag as index in your NSArray or WhatEver you're using for storing data.
}
When you are creating button then set tag to button.
btn.tag= indexPath.row;
and when your button is press then access button with tag value
-(void) buttonPressed: (UIButton *) sender
{
UIButton *btn = (UIButton*)sender;
switch (btn.tag) {
case 0:
//Thing you want to perform
break;
default:
break;
}
}

Getting a button press from a custom UITableViewCell's button

I have a project with a custom UITableViewCell (cell.h/.m/.xib) that has 2 labels (labelMain/labelSub), and 2 buttons on it (buttonName/buttonInfo) linked to 2 actions (showName/showInfo).
What I want to do is be able to access the 2 actions in my projects main viewcontroller so that when showName is pressed, a textfield.text in the viewcontroller (not in the cell) is set to that specific cell's labelMain.text.
Hope that makes sense. My problem is that if I write the action (showName) in the cell.m, I cannot access the textfield from my main viewcontroller. On the flip side, if I write the action in my viewcontroller, how do I know which button inside which cell was tapped?
Hope this makes sense...
Use tag can identify which button in which cell is being tapped.
- (UITableViewCell *)tableView:(UITableView *)tableViews cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//init identifier
if (cell ==nil)
{
//load nib file
}
buttonName.tag = indexPath.row;
[buttonName addTarget:self action:#selector(showName:) forControlEvents:UIControlEventTouchUpInside];
buttonInfo.tag = indexPath.row;
[buttonInfo addTarget:self action:#selector(showInfo:) forControlEvents:UIControlEventTouchUpInside];
}
}
-(void) showName:(UIButton*)button{
int row = button.tag; //you know that which row button is tapped
}
-(void)showInfo:(UIButton*)button{
int row = button.tag;//you know that which row button is tapped
}
---------------- EDIT -------------
If you need to know which button is pressed based on row & section, you may try this below. (in cellForRowAtIndexPath: method)
int tag = (indexPath.row+1)+(indexPath.section*100);
buttonName.tag = tag;
When button at
row = 5, section = 0 then tag = 6.
row = 4, section = 3 then tag = 305.
row = 0, section = 11 then tag =1101.
limitation, row cannot be more than 99. and DON'T use positive tag for other view. if you need use tag, try negative. (-1, -9, -100).
so from here, you can calculate back row & section of indexPath. using this :
-(NSIndexPath*)getIndexPathFromTag:(NSInteger)tag{
/* To get indexPath from textfeidl tag,
TextField tag set = (indexPath.row +1) + (indexPath.section*100) */
int row =0;
int section =0;
for (int i =100; i<tag; i=i+100) {
section++;
}
row = tag - (section*100);
row-=1;
return [NSIndexPath indexPathForRow:row inSection:section];
}
how to use :
-(void)showInfo:(UIButton*)button{
NSIndexPath *indexPath = [self getIndexPathFromTag:button.tag];
int row = indexPath.row;
int section = indexPath.section;
}
Try this in viewController.m file in cellForRowAtIndexPath method
[[customCell showNameBtn] setTag:indexPath.row];
[[customCell showNameBtn] addTarget:self action:#selector(showName:) forControlEvents:UIControlEventTouchDown];
-(void) showName:(id)sender
{
// check here the sender tag and then perform you action what you want.
}
I suggest to use delegate(protocol) method for this. You will be having full control on the button, cell and the view controller. And its very simple too
The simplest solution in my opinion:
In your CustomCell.h :
#property (nonatomic, copy) void (^buttonTapAction)(id sender);
In your CustomCell.m create the IBAction and connect it to your UIButton :
-(IBAction)cellButtonIsPressed:(id)sender{
if (self.buttonTapAction) {
self.buttonTapAction(sender);
}
}
Then in the ViewController.m where your UITableView is managed :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString* cellIdentifier = #"customCell";
CustomCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.buttonTapAction = ^(id sender){
//Do what you want to do when the button inside THIS cell is clicked
};
}
Try to create the button dynamically, with its methods in same controller. Do this in cellForRowAtIndexPath: method:
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"WorkRequestedCC" owner:self options:nil];
{
for (id oneObject in nib) if ([oneObject isKindOfClass:[WorkRequestedCC class]])
cell = (WorkRequestedCC *)oneObject;
}
UILabel *costLbl=[[UILabel alloc]initWithFrame:CGRectMake(792, 13, 10, 15)];
costLbl.text=#"$";
[costLbl setBackgroundColor:[UIColor clearColor]];
UITextField *txtCost=[[UITextField alloc]initWithFrame:CGRectMake(805, 10, 94, 27)];
txtCost.backgroundColor=[UIColor whiteColor];
[txtCost setKeyboardType:UIKeyboardTypeNumberPad];
txtCost.text=obj.expCost;
[txtCost addTarget:self action:#selector(textChanged:) forControlEvents:UIControlEventEditingChanged];
[cell.contentView addSubview:costLbl];
[cell.contentView addSubview:txtCost];
cell.lblDes.text=obj.expDes;
}
- (void)textChanged
{
//your code here
}

Fetching Values from textField in a custom cell iPhone

I have a custom cell in a table View, see below.
I have two textFields txt1 and txt2 in my custom cell, as seen below
How can i access the values i enter in each of the text fields so that i can add the values in to seperate Arrays...
the "Addset" button will increment the no of sections of the grouped table View there by incrementing the one more set.
my table view code is as follows.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID= #"catogoryCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:cellID];
if(cell==nil)
{
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:nil options:nil];
for(id currentObject in nibObjects)
{
if([currentObject isKindOfClass: [CustomCell class]])
{
cell = (CustomCell *)currentObject;
}
}
}
//cell.txt1.text = #"0";
return cell;
}
Thanks all..
Cells are reusable, so they need a more persistent way to keep their info.
Method 1:
You could hold some UITextField objects into an array in case you don't want to reuse the textfields as well, and at cellForRowAtIndexPath you'd only need to set the textfields to their cells such as:
cell.txt1 = [textFieldsArray objectAtindex:indexPath.section*2];
cell.txt2 = [textFieldsArray objectAtindex:indexPath.section*2+1]; //txt1 and txt2 properties should have assign
Method 2:
If you want to reuse the textfields as well I suggest using an array with mutable dictionaries, each dictionary holding the 'settings' for a cell. The textfields will be fully managed by the custom cell (e.g: at the UIControlEventValueChanged event update #"txt1" or #"txt2" values from the dictionary attached to the cell).
///somewhere in the initialization (in the class holding the tableview)
contentArray = [[NSMutableArray alloc] init];
///when adding a new cell (e.g: inside the 'Add set' action)
[contentArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:#"", #"txt1", #"", #"txt2", nil]];
//add a new cell to the table (the same way you do now when tapping 'Add set')
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
...
[cell attachDictionary:[contentArray objectAtIndex:indexPath.section]];
return cell;
}
///anywhere where you'd like to access the values inserted inside a cell
NSMutableDictionary *cell3Content = [contentArray objectAtIndex:3];
NSString *text1 = [cell3Content valueForKey:#"txt1"];
NSString *text2 = [cell3Content valueForKey:#"txt2"];
///CustomCell.m
-(id)initWithCoder:(NSCoder *)decoder{
self = [super initWithCoder:decoder];
if(!self) return nil;
[txt1 addTarget:self action:#selector(txt1Changed:) forControlEvents:UIControlEventValueChanged];
[txt2 addTarget:self action:#selector(txt2Changed:) forControlEvents:UIControlEventValueChanged];
return self;
}
-(void)attachDictionary:(NSMutableDictionary *)dic{
contentDictionary = dic;
txt1.text = [contentDictionary valueForKey:#"txt1"];
txt2.text = [contentDictionary valueForKey:#"txt2"];
}
-(void)txt1Changed:(UITextField *)sender{
[contentDictionary setValue:txt1.text forKey:#"txt1"];
}
When you make the IBOutlet connections in your UITableViewCell subclass, connect them to properties in the File Owner (the viewController), instead of the view itself. That way you'll be able to access them from your viewController (the UItableViewDataSource)

UISwitch in TableViewCell - Change cell's text upon switching

I want a UISwitch within a TableViewCell to change the text from 'Active' to 'Disabled' and vice versa when switched but when the switch changes, all the data in my table view disappears. I'm using 'reload data' since I do not know how to change a specific cell's text.
FYI, 'current item' is a core data entity with a BOOL property 'itemEnabled'.
The switch is only visible during 'editing mode'.
I have a UISwitch in a table view cell within my 'detail view controller':
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
NSString *cellDetail = nil;
static NSString *EnabledCellIdentifier = #"Enabled";
cell = [tableView dequeueReusableCellWithIdentifier:EnabledCellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:EnabledCellIdentifier] autorelease];
UISwitch* actSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[cell setEditingAccessoryView:actSwitch];
[actSwitch addTarget:self action:#selector(actSwitchChanged:) forControlEvents:UIControlEventValueChanged];
if ([[currentItem valueForKey:#"itemEnabled"] boolValue]) {
cellDetail = #"Active";
actSwitch.on = YES;
} else {
cellDetail = #"Disabled";
actSwitch.on = NO;
}
[actSwitch release];
cell.textLabel.text = cellDetail;
return cell;
}
I have a method to receive the action:
- (void)actSwitchChanged:(id)sender {
UISwitch* swEnabled = (UISwitch*)sender;
NSManagedObjectContext* itemContext = [currentItem managedObjectContext];
currentItem.itemEnabled = [NSNumber numberWithBool:swEnabled.on];
NSError *error = nil;
if (![itemContext save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
Here is an approach to getting the cell from within the action method that does not require subclassing UISwitch:
- (void)switchAction:(id)sender {
// Cast the sender as a UISwitch
UISwitch *aSwitch = (UISwitch *)sender;
// Cast the superview of aSwitch to a UITableViewCell
UITableViewCell *cell = (UITableViewCell *)aSwitch.superview;
// You could get an indexPath as follows (though you don't need it in this case)
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// Set the text of the label in your cell
cell.textLabel.text = aSwitch.on ? #"Active"; : #"Disabled";
}
You can get a specific cell with -[UITableView cellForRowAtIndexPath:]. You just need to know the index path of the cell (also note that you are asking the tableview for the cell, not calling the delegate method).
So I subclassed UISwtich and included property for storing the cell's index path, which can then be used in the action method:
- (void)actSwitchChanged:(id)sender {
TLSwitchInCell* swEnabled = (TLSwitchInCell*)sender;
currentItem.itemEnabled = [NSNumber numberWithBool:swEnabled.on];
UITableViewCell* theCell = [self.tableView cellForRowAtIndexPath:swEnabled.cellIndexPath];
theCell.textLabel.text = swEnabled.on ? #"Active" : #"Disabled";
}
Another variation on a theme! If you have lots of settings fields with switch buttons you can use something like this to grab the label text associated with the switch button that was trigger! You can set the text using usual methods!
#IBAction func switch(sender: UISwitch) {
let labelIndex = sender.superview!.subviews.indexOf({$0 is UILabel})
NSLog("The text from the label associated with this switch is %#",
(sender.superview!.subviews[labelIndex!] as! UILabel).text!)
}