iPhone table view - some button/action questions - iphone

I created a table view that is populated with a custom UITableViewCell (like this). Each of the cells contains two UIButtons. I assign the action to the button like this:
[decreaseButton addTarget:self action:#selector(decrease) forControlEvents:UIControlEventTouchUpInside];
Is this the right way?
Anyway, it works, but in my "decrease" method I need to know in which of my 18 table view rows the button was pressed. indexPath.row doesn't work outside the cellForRowAtIndexPath method, of course.
Can someone explain me how to do this?
Thanks a lot in advance!
iYassin

You can do this in two ways.
Inspecting the Event Sender
Change your decrease method from:
- (void)decrease;
to:
- (void)decrease:(id)sender;
That way when decrease is called, you'll be given a reference to the button that had the touch up inside event.
Define the decrease Method Closer to the Information
Another solution would be to have a different target instance for each button (for example, implement the decrease function as part of the custom cell). That way you know the button that was touched was the one for the current cell.

The way i solved this is I keep track of data i might need inside my custom cell object. And the button is connected not to the external receiver but the cell it's self which in-turn knows how to call the real receiver of the action.
I make my cell with something like:
cell = [[MyTableViewCell alloc] initWithStyle:style
reuseIdentifier:CellIdentifier];
And I have a setup method so i can re-init a cell when I dequeue it:
[cell setupMyCellWithContext:objectID
target:[[UIApplication sharedApplication] delegate]
action:#selector(someAction)];
so inside your cell class you use the action and target that was sent in the setup method to call the true target:
- (void)doAction:(id)sender {
if ([target respondsToSelector:action]) {
[target performSelector:action withObject:objectID afterDelay:0];
}
}
So when your user taps the button, the os calls [cell doAction:], which calls the target and action selector you set up before hand with the correct context object.

Related

How to call button Clicked method from somewhere else

I am developing an application in which I want to select the button with some given tag. For example tag=12. So, what I want is that when the button with tag 12 is selected the button clicked method also gets called.
One more thing I want to ask, if I write
button.selected=YES
will the button method automatically get called? If not then how to call the button method from somewhere else where I do not have sender (button properties) value?
The only thing I have is the button tag.
Please help and ask me for any clarification.
Create a temporary UIButton and give the tag of button you want to call.
For eg. call button action method with temporary button of tag 12
UIButton *button = [[UIButton alloc] init];
button.tag = 12;
[self buttonTapped:button];
Hope it helps. Comment down for any query.
If you're setting button's property to Selected manually , then for it's click event you will have to call it manually , When you set button Selected like :
[self buttonCick];
iUser is close. You'll want to call the method you've linked to your button manually.
[self buttonClick:nil]
will work, if you're calling the buttonClick method from an object of the same class that contains the buttonClick method. Otherwise, you'll need to keep a reference to the object (perhaps a controller) containing the buttonClick method and use that instead of self.
[self.controller buttonClick:nil];

Reload data for UIView\UIViewController?

When I am moving the buttons on the screen from a function, [self makeButtons], nothing happends unless I push a viewcontroller, then pop back. Is there a reload data function for ViewController, as it is for UITableViews? I am using NavigationController, and I am adding subviews to a UISrollView and moving other buttons on the screen. The method is called after fetching data with ASIFORMHTTPRequest.
EDIT: I am sorry I didn't specify more.
I have a method that is sending a [request startAsynchronous] (ASIFORMHTTPrequest).
I have a NSMutableArray containing all my buttons. When the request is done, a method called doneGettingRequest, which looks like this.
- (void) doneGettingRequest(ASIFORMHTTPRequest *) request {
[self removeButtons];
}
which is calling this method;
- (void) removeButtons {
NSLog(#"Removing buttons!");
for (UIButton *button in gameButtons) {
[button removeFromSuperview];
}
Everything works when I go to another view, then back again. The problem is it won't refresh if THAT view is being shown when the method is called (which will happend almost always). The gameButton is a NSMutableArray containing buttons that are currently being showed. When I am done removing them, I want to add some other buttons. The problem is, the buttons is not removed when the removeButtons is called. The message "Removing buttons!" however, is shown, so the method is being called.
Any suggestions?
Thanks
You can put your logic in your viewWillAppear.
This method is called before the receiver’s view is about to be added to a view hierarchy and before any animations are configured for showing the view.
You can override this method to perform custom tasks associated with displaying the view.
If you override this method, you must call super at some point in your implementation.
Have you tried
[view setNeedsDisplay];

iPhone: IBAction vs Selector

I have a Button1 which has IBAction. Also I set target and action for my button
- (void)setTarget:(id)target action:(SEL)action {
[self.Button1 addTarget:target action:action
forControlEvents:UIControlEventTouchUpInside];
}
So when I pressed the button firstly IBAction did what he should, and than action that I set to button. Is that order always be like that ?
If you are loading you view or view controller from a nib file then yes the pattern will always be the IBAction even first followed by the target you have added to the button.
In effect adding an IBAction in Interface Builder is really just telling IB to call ["UIControl" addTarget:"id" forControlEvents:"UIControlEvent"], and you can add multiple targets to a UIButton.
In effect your code will load everything from the NIB file first (if you are using initWithNib:named:), so this will call the addTarget function on the button first with the action you have specified in Interface Builder, then at some later point the setTarget function you have above will get called, which will add another target action to the button. A UIControls targets are stored in an array which is accessed in order and will trigger if control events are met in the order they were created in.
If you look in the header file for UIControl (the super class for UIButton) you will see that NSMutableArray* _targetActions is an array. So the order is guaranteed to fire like this unless you reorder this array after it is created at some point.

Code for Reset Button in iPhone

I have a button called Reset in my iPhone application. It is for resetting purposes. I called viewDidLoad() method for this. Is it right?
How to reset a page in iPhone?
how to write code for this? Any help would be appreciated.
You should not call -viewDidLoad in your own code. It gets called on view controllers (VCs) when their view has just finished loading.
To return a VC to its original state depends largely on the specifics of the situation, but you could probably either set its properties and whatnot back to their original values or you could alloc and init a new VC, remove the old VC's view from the view hierarchy and add the new VC's view.
Alternately, you could just implement a -resetToOriginalState method on your VC.
resetToOriginalState is not a inbuilt method, you have to write this method on your own and instead of calling viewDidLoad call this method 'resetToOriginalState:' when the respective button is clicked. If you are creating button programmatically you can set the target/action of that button like this:
resetBtn is the instance of the UIButton:
UIButton *resetBtn = [[UIButton alloc] initWithFrame:CGRectMake(x,y,w,h)];
[resetBtn addTarget:self action:#selector(resetToOriginalState:) forControlEvents:UIControlEventTouchUpInside];
- (void)resetToOriginalState:(id)sender {
//Do your stuff here
}
If your using Interface Builder connect the action method (resetToOriginalState) to the button.

iPhone SDK 2: Programmatically adding an Info Button

I am trying to add an info button to my app to provide custom help.
Instead of adding the button to the nib and linking the event (touchUpInside) to the controller, I decided to add the button programmatically. The button shows up. When I add the target event handler to be executed when the button is touched, it does not work. That my method(doHelp) is not being called on touching the button.
When I debugged it, the event is not registered with the button! Although the code does not throw any exceptions.
Here is the code snippet FROM the view:
// Create a Button to get Help
UIButton *helpButton = [UIButton buttonWithType:UIButtonTypeInfoDark ] ;
buttonRect = helpButton.frame;
// CALCulate the bottom right corner
buttonRect.origin.x = rect.size.width - buttonRect.size.width - 8;
buttonRect.origin.y = rect.size.height - buttonRect.size.height - 8;
[helpButton setFrame:buttonRect];
[helpButton addTarget:self action:#selector(doHelp:) forControlEvents:UIControlEventTouchUpInside];
[helpButton setEnabled:TRUE];
[self addSubview:helpButton];
........
// Another METHOD ELSEWHERE in the VIEW object
-(void)doHelp:(id)Sender
{
[self setHelpNeeded:TRUE];
[self setNeedsDisplay];
}
What am I doing wrong please?
I have looked at the SDK help and samples and am really flummoxed!
Am hoping another pair of eyes will help! :-)
This code snippet is in the View Object in case you need to know.
I just added the doHelp to help the first 2 responders... thanks.
**UPDATE 6/4/09 ** -
I have been trying all night and nothing worked. I think there is something wrong in the way I have set up the method selector as my method never gets called. Everything else looks fine. Even using a NIB file does not work. I have tagged the button, retrieved it and added the method selector but to no avail. There is something fundamental which I am doing wrong... Argh!!!
Any ideas, anyone?
Resolved it finally!!! and learnt something in return. Did cost me a few days to figure this out.
The reason my UIButton object was not working was because I found that in case of a UIIMageView object:
"initWithImage: This method adjusts the frame of the receiver to match the size of the specified image. It also disables user interactions for the image view by default."
AND my UIButton had been assigned as a subview of a UIImageView control !!!
There was no errors / warnings. It just gets disabled quietly.
Solution: Created a container UIView object which now contains the UIImageView AND the button so that the button appears as overlayed on the Image but it is actually a sibling of the image and a subview of the dummy container UIView.
It's been awhile, but I think your addTarget needs to take the object that contains the doHelp: selector, like so:
[helpButton addTarget:self action:#selector(doHelp:)];
assuming somewhere in that same View you have:
- (void)doHelp: { }
passing nil to addTarget means that you're sending that selector to no recipient.
The problem is your addTarget:nil there. The selector you gave it for action is just a message it'll send to its target. You didn't give it a target, so it doesn't know what to do with that message. You probably want to pass in self instead of nil there.
I came across this while googling for a solution to the same problem. At least with the 3.x SDK, all you have to do is set the UserInteractionEnabled property of the UIImageView to YES.
Thanks for posting your discovery about the problem, I wouldn't have even thought to look at that one.
I had a similar problem where Buttons were outside of the view and did not receive tap messages
what helps is to set background colour of the parent view, to see that button is outside of it:
...
[buttonParentView addSubview: myButton];
buttonParentView.backgroundColor = [UIColor cyanColor];