Core data objects actions from buttons - ios

In my app I am showing core data objects, in this case it is a Tasks Manager.
I have included a swip gesture to the rows, when the user swipes from left to right, an UIView is shown at the right side of the screen, like in the following picture:
This is the code for the handleGestureLeftRight method:
-(void)handleGestureLeftRight:(UIGestureRecognizer *)gec
{
{
CGPoint p = [gec locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
if (gec.state == UIGestureRecognizerStateEnded) {
NSLog(#"GESTURE LEFT-->RIGHT DONE");
//BUTTONS AND LABELS DEFINITIONS ARE NOT SHOWN TO AVOID LONG CODE HERE
}
}
}
I would need your help on how to implement core data actions when the user taps on the buttons on the right side. As example, if the user taps on the Done button, the selected row object, should change the value of an attribute called isDone. The same should happen tapping to the other buttons, but a different attribute value should be changed.
Thank you.

When you add the buttons to your table view in handleGestureLeftRight:, save
the selected index path in a property:
CGPoint p = [gec locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
self.currentIndexPath = indexPath;
Then, in the button action methods, you can access the corresponding Core Data object
with
YourEntity *object = [self.fetchedResultsController objectAtIndexPath:self.currentIndexPath];
and update its properties. When removing the the buttons, set
self.currentIndexPath = nil;

Related

Custom Cell button Click

My scenario is as follow's:
Custom Cell View
1) I am populating data from server in the custom cell view which is perfectly populated, i want a link store in my array which i want to open in browser, so i want to check which index.row button is clicked so that against that row i can get the url link and open it in browser, so far i have found the solution of button tags but that doesn't work's as well, as if we have two cell's in the screen at same time on click of button both button return's same tag.
2) As the image attached i have another storyboard in which i want to segue to a new view controller, same as mentioned above, i want to pass a specific post title and key as well.
I hope every thing is clear.
Thank's in advance.
To answer the first part of your question. Tags are a pain. It's better to pass along the UIButton as the sender, and, in the action for the button, then you can say something like:
-(void) buttonPresse:(UIButton *)sender
{
CGPoint location = [self.tableView convertPoint:sender.bounds.origin fromView:sender];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
UITableViewCell *cell = [self.table cellForRowAtIndexPath];
//Do what you want with the cell or indexPath
}
I have found the solution of button tags but that doesn't work's as well
Perform following steps to detect which button is selected.
Type the code snippet given below in cellForRowAtIndexPath: method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// DEFINE CELL
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// SET ACTION METHOD ON CALL BUTTON
UIButton *button = (UIButton *) [self.view viewWithTag:40];
[button setUserInteractionEnabled:YES];
[button addTarget:self action:#selector(checkButtonTapped:) forControlEvents:UIControlEventAllTouchEvents];
}
Add following method for checkButtonTapped:.
- (void)checkButtonTapped:(UIButton *)sender
{
// GET POINT OF THE BUTTON PRESSED
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
// GET INDEXPATH FOR THE CELL WHERE THE BUTTON IS PRESSED
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil)
{
//Use indxPath.row to get item
//Perform operations
}
}
There is another approach if you want to perform action according to the cell selected by the user.
For the case where you want to check which row of the cell is clicked you should use following method.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"ShowindexPath%ld", (long)indexPath.row); }
Here we check for the user interaction on cell. indexPath.row will return index number for the cell selected by user. You can perform other actions in place of NSLog method.
For the purpose to send value while performing segue use following steps:
Create property in the NewViewController.h file where you want to perform segue as follow:
#property (nonatomic) NSString* receivedValue;
#synthesize property by writing following code in NewViewController.m file within #implementation and #end
#synthesize receivedValue;
ImportNewViewController.h file in TableViewController.m file.
Go to prepareForSegue: method in the TableViewController.m file from where you want to send the value and write following code according to your class names within it.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NewViewController *nVC = [segue destinationViewController];
[nVC setReceivedValue:sendValue];
}
Here sendValue is the value that you want to send.
That's all.
Build and run your project and enjoy.
You can extend UITableViewCell and add a touple property to it. key containing the index.row and value containing the URL eg:- 1:"www.stackoverflow.com". When you click on a button, all you have to figure out is the index.row and from that you can get the value that you are looking for.
you can add target for button in cellForRowAtIndexPath like :
[cell.yourButton addTarget:self action:#selector(buttonAction:event:) forControlEvents:UIControlEventTouchUpInside];
here you can receive the action for this button
-(void)buttonAction:(UIButton *)sender event:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPos = [touch locationInView:self.tblview];
NSIndexPath *indexPath = [self.tblview indexPathForRowAtPoint:touchPos];
if(indexPath != nil){
// handle click event..
}
}
surely it will work.........

How to Change an UIImageView Image in a Table cell, on a button click from the cell?

I created a custom table view which has custom cells,
Each cell contains an image and a button (amongst other text)
I want to be able to change the image in the UIImageView when the button is clicked,
I am able to get the click event. I however am having a difficult time changing the image.
I have attempted to get the entire cell in order to change the image using that :
UIButton *senderButton = (UIButton *)sender;
NSIndexPath *path = [NSIndexPath indexPathForRow:1 inSection:senderButton.tag];
LocationCardCell* cell = (LocationCardCell *) senderButton.superview.superview.superview;
if ([cell.class isSubclassOfClass:[LocationCardCell class]]) {
NSLog(#"cell is RIGHT CLASS!!!");
}else{
NSLog(#"cell is not THE RIGHT CLASS!!!");
}
UIView *cellContentView = (UIView *)senderButton.superview;
LocationCardCell *cell1 = (LocationCardCell *)cellContentView.superview;
if ([cell1.class isSubclassOfClass:[LocationCardCell class]]) {
NSLog(#"cell1 is RIGHT CLASS!!!");
}else{
NSLog(#"cell1 is not THE RIGHT CLASS!!!");
}
Can somebody please let me know how to go about getting the cell from the button click?
Keep this method in your arsenal...
- (NSIndexPath *)indexPathWithSubview:(UIView *)subview {
while (![subview isKindOfClass:[UITableViewCell self]] && subview) {
subview = subview.superview;
}
return [self.tableView indexPathForCell:(UITableViewCell *)subview];
}
Then,
- (IBAction)pressed:(id)sender {
NSIndexPath *path = [self indexPathWithSubview:(UIButton *)sender];
LocationCardCell* cell = (LocationCardCell *)[self.tableView cellForRowAtIndexPath:path];
// carry on happily
But not too happily. You question doesn't state what you plan to do with that cell once you have it. The generally right approach to modifying tableview cells is to modify your model, reload the cell, and then account for that change in the datasource (tableView:cellForRowAtIndexPath:).
A more conventional pattern would be to use the indexPath we just found to dereference your model, modify it, then reload.

How to get the indexPath from a textField in a cell, when didEndOnExit calls a custom method

this is my first question. I wouldn't be asking but after reading the documentation and trying lots of code from stack overflow I'm still stumped. I've just started learning code recently, so yes, I am a dumb-ass and wouldn't be surprised if I've made some fundamental error(s).
What I'm trying to do: in a custom cell's textField, a number is entered and on exit the saveGoal method is called in the CustomCellClass.m (code shown below). The saveGoal method creates a goalsArray from the text file of previous entries (if there's no data the text file is created. I omitted that code because it works). This is where it gets difficult (for me). I need the indexPath of the cell which called the method so I can insert the user entry... But I don't know how to get the cell object to use as a parameter in indexPathForCell.
- (IBAction)saveGoal:(id)sender {
// Saving the user entry in a string
self.goalString = [NSString stringWithFormat:#"%#\n",self.goal.text];
// Instance variables
NSError *err = nil;
NSMutableArray *goalsArray = [NSMutableArray arrayWithContentsOfURL:self.goalsURLMethod];
// If there is data in the text file
NSIndexPath *indexPath = [[NSIndexPath alloc] init];
// Ideally I'd like to do something like this (There is an IBOutlet from the
// table view in the storyboard to a tableView property).
indexPath = [self.tableView indexPathForCell: UNKNOWN CELL PARAMETER];
// Then based on the indexPath I can insert or replace objects in the array
if(indexPath == 0) {
// masterful code
} else {
// If it's another row, replace the object. Something like this:
[goalsArray replaceObjectAtIndex: indexPath.row withObject: self.goalString];
[goalsArray writeToURL:self.goalsURLMethod atomically:YES];
// Then update the view
[self.tableView reloadData];
}
}
}
A solution would be much appreciated!
If you have a custom cell, add a property to it:
#property (strong, nonatomic) NSIndexPath *indexPath;
and set it when you return the cell for display. Now the cell has access to the required information.
Aside:
Not that you're going to use it any more, but don't do this:
NSIndexPath *indexPath = [[NSIndexPath alloc] init];
indexPath = [self.tableView indexPathForCell: UNKNOWN CELL PARAMETER];
because creating an instance just to destroy it in the next statement is wasteful
Or you could just do it like this into the action method of your choice:
CGPoint hitPoint = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *hitIndex = [self.tableView indexPathForRowAtPoint:hitPoint];

iOS >> UITableViewCell >> Custom Cell >> Row Number

Does a UITableViewCell (or a subclass of) has a way to recognise 'on the run' in which Row it is currently at? - not via the didSelectRowAtIndexPath method...
If I subclass UITableViewCell and have some control objects in it (button, text field, etc...), and I wish to respond to that control usage, I wish to respond in consideration to the cell current row; doing so in MYTableViewCell.m file.
What I have done so far, is assign the tag Property with the Row number at creation time (cellForRowAtIndexPath); and then I can create my own Protocol in the MYTableViewCell file, create a 'delegate' Property and assign each cell to the VC as its delegate and send it messages. But that seems like a lot to do for something so basic.
Is there a 'built in' way to do that?
Or a simpler way...
Check out the
- (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell
method. I tend to add a tableView property to the cell and set it when creating the cell to the tableView that will own that cell. Then call:
[tableView indexPathForCell:cell]
Which returns the indexPath for that cell, giving you the section and row. This is better than using a tag of course, since it includes the section, and is always valid, even if the cell changes position (others inserted or deleted above it, or it actually moves).
Well you can use the cellatrowforindexpath method to perform such action.
for example if you want to perform some action on button click, you can do like that.
cell.buttonName.tag=indexPath.row;
and in the action that you have attached to that button do like that.
(ibaction)performsomeAction:(id)sender{
UIButton *btn=(UIButton*)sender;
nslog(#"the row on which i have clicked is %d",btn.tag);
}
this will tell you which row you are currently.
There are different ways to obtain the index path of a cell after touching a control inside it, without using the tag property or coupling the cell with its table view.
The first thing to do is to add the target-action to your button, like this:
[button addTarget:cell action:#selector(buttonTapped:withEvent:) forControlEvents:UIControlEventTouchUpInside];
Then you can use the event parameter of the action method:
- (void)buttonTapped:(id)sender withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
// ....
}
Or the view hierarchy to retrieve the cell:
- (void)buttonTapped:(id)sender withEvent:(UIEvent *)event
{
UITableViewCell *cell = (UITableViewCell *)[[sender superview] superview];
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// ....
}
Or the position of the sender (i.e. the control):
- (void)buttonTapped:(id)sender withEvent:(UIEvent *)event
{
CGPoint position = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:position];
// ....
}

Custom UITableViewCell and IBAction

I have a custom UITableViewCell on which I have added a button, I have associated that button on an IBAction in my viewController. Now the problem that i am facing is how do I know from which cell that button was created. When I present my viewController which has a table in it and has multiple rows (custom UITableViewCell), now when the user presses the button the action is getting called, but how do I know which row was it.
Because based on the row index I need to store some value.
Edit: I have some clue on it now, but still I am not sure how will I do it, so it seems like on my tableViewController cellForRowAtIndexPath method I have to do something like this
[cell.button1 addTarget:self action:#selector(addToCart:) forControlEvents:UIControlEventTouchUpInside];
And then I have to write a method
-(IBAction) addToCart:(id) sender
But still what I don't know is how do i get the row index in my addToCart method.
Appreciate your help.
Ok, finally I got the answer, looking into different forums, people were suggesting to do something like this
in the custom table view controller in cellForRowAtIndexPath do this
cell.addToCart.tag = indexPath.row;
[cell.addToCart addTarget:self action:#selector(addToCart:)
forControlEvents:UIControlEventTouchUpInside];
where addToCart is name of UIButton in my customUITableViewCell. It didn't seems to work for me. So this is what I did
-(IBAction) addToCart:(id) sender{
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)
[[sender superview] superview]];
NSLog(#"The row id is %d", indexPath.row);
}
And then through interfacebuilder I associated the action of my button to addToCart IBAction on my table view controller.
Much less hackerific.
[cell.button1 addTarget:self action:#selector(addToCart:event:) forControlEvents:UIControlEventTouchUpInside];
- (void)addToCart:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];
}
The accepted answer does not work any more. Please refer to this post
It does it that way:
- (void)checkButtonTapped:(id)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil)
{
...
}
}
Many of the developer used custom view to show custom cell on Table view for older version of iOS. If you are one of them, then you will have to face a problem that your button click action will no longer work with iOS7.
How to resolve this:
You have two options:
Option 1: Create the new lay out with new table cell instead of taking view. and put all layouts again in table cell.
I know, this will require a lot of effort.If you don't want to do this, we have a very small hack for it:option 2
Option 2: Create a IBOutlet for your button and add this button as a subview of your cell's content view.
[self.myCell.contentView addSubview:self.btn_click];
The above line of code will add btn_click as a subview of you content view. Now button click action should work.

Resources