Pass custom parameters to button action method - objective-c

I am loading a bunch of images into a UIScrollView, I then resize them and position a button over each, so when I click on the button over the smaller image, it will load up the full size image in a new view.
I am struggling to find a decent way to somehow pass the image's URL to the click handler as a parameter when the button is clicked, and from what I have read, passing parameters to callback functions is not possible.
Here is the code I have thus far,
for(Card *card in crd){
pocketImage = [self imageWithImage:[UIImage imageNamed:#"pocket.png"] scaledToSize:CGSizeMake(245/2,80/2)];
pocketImageView = [[UIImageView alloc] initWithImage:pocketImage];
cardImage = [self maskImage:[UIImage imageNamed:#"animal.jpg"]];
cardImageView = [[UIImageView alloc] initWithImage:cardImage];
y = (80/2) * inc;
if (inc % 2){
x = 125;
} else {
x = 10;
y += (80/2);
}
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn addTarget:self action:#selector(testMe) forControlEvents:UIControlEventTouchUpInside];
[btn setFrame:CGRectMake(x,y-40,pocketImageView.frame.size.width,pocketImageView.frame.size.height*2)];
[pocketImageView setFrame:CGRectMake(x,y,245/2,80/2)];
[cardImageView setFrame:CGRectMake(x,y-40,245/2,80/2)];
//add the pocketImageView to the container
[imageContainer addSubview:cardImageView];
[imageContainer addSubview:pocketImageView];
[imageContainer addSubview:btn];
inc++;
}
Callback function,
-(void)testMe {
NSLog(#"works");
}
So basically that just loops through all of the images, and then appends all of them to a UIScrollView, which works fine, the problem comes in when I try to pass custom parameters to the testMe method, which isn't possible as far as I know, so how would I be able to click on the button and then display the corresponding full size image in a new view?

You can use an iVar / (private) #property for this.
Just set the data you want to have available like this:
myTransferVariable = // something you need in you testMe method
and use it like this
-(void)testMe {
NSLog(#"%#", myTransferVariable);
}

You should be able to define your action as - (void)testMe:(id)sender { and specify it as #selector(testMe:). If you then give each button a tag that is (for example) an offset into an array of URL strings, the method should be able to find a URL that matches the selected button by using ((UIButton *)sender).tag.

Related

When clicking first button,it becomes highlighted and while clicking second,second highlighted and first become normal

I am creating an app,which contains five buttons ,created programmatically.The following are the requirements...
while clicking the first button it stay highlighted.while clicking second button ,first become normal and second stays highlighted...ie the particular button clicked becomes highlighted ,all others remains normal.......please help..
You can set
[button setBackgroundImage:[UIImage imageNamed:#"normalbackgroundimage"] forState:UIControlStateNormal]; //not highlighted
[button setBackgroundImage:[UIImage imageNamed:#"highlightedbackgroundimage"] forState:UIControlStateHighlighted | UIControlStateSelected]; //highlighted
and now when you set your button.selected = YES it will get highlighted
so you could do something like this on button click
button1.selected = YES;
otherButton.selected = NO;
EDIT
Simple solution to your problem would be to create one ibaction connect it to all your buttons you want to selected/deselect and just do this
-(IBAction)someButtonPressed:(UIButton*)sender{
button1.selected = NO;
button2.selected = NO;
button3.selected = NO; //and so on...just set all your buttons to selected = NO
//at the end you just select button you clicked
sender.selected = YES;
}
This would be my solution to this:
Get a property to keep track of the selected button
#property (nonatomic, weak) UIBUtton *lastSelectedButton;
In your button callback method (the selector you configured when you added the buttons):
- (void)didClickButton:(UIButton *)button {
if (self.lastSelectedButton isEqual:button) {
// Don't need to do anything in this case because the button is already selected
return;
}
[self.lastSelectedButton setSelected:NO];
[button setSelected:YES];
[self setLastSelectedButton:button];
}
Let me know if you have questions or need more help!
You can create a instance variable int which holds a tag value. Now which ever button you click you need to clear the previous button's tag value and assign it to the current button.
For Ex:
int const TAG_HIGHLIGHTED_BUTTON = 100;
- (void)buttonAction:(UIButton *)button {
UIButton *prevButton = [self.view viewWithTag:TAG_HIGHLIGHTED_BUTTON];
[prevButton setTag:0];
[button setTag:TAG_HIGHLIGHTED_BUTTON];
}

User defined iOS interface

Introduction
I am writing an app where the interface on a screen can vary depending on user input on the previous screen. What I'm trying to do right now is load up x amount of sliders, where I get x from the previous screen. The real issue I'm having is won't each slider I use have to be named and defined? I've thought of a way to do this but I'm not entirely sure how to implement if you could advise me it would really be appreciated
Pseudo Code
-(void) loadInterface {
// Set up a frame
CGRect myFrame = CGRectMake(10.0f, 100.0f, 250.0f, 25.0f);
for (int i = 0; i < x; i++) {
[self newSlider]
// Retrieve info here about the slider and pass it to newSlider
}
}
-(void) newSlider (info about slider) {
// Here I need the code to load a slider
// If I use something like this:
// UISlider *slider1 = [[UISlider alloc] initWithFrame:myFrame];
// The next time this method is loaded the slider will be overwritten right?
}
You could use an NSMutableDictionary to keep track of all your sliders, although maybe you do not need that at all.
In newSlider you create a slider and you should add it to some view (I assume self) through
[self addSubview:slider];
All sliders thus created will appear at the position where you created them and will not disappear unless you remove them from the view.
You could take this snippet as an example of how you can create a slider:
CGRect frame = CGRectMake(0.0, 0.0, 200.0, 10.0);
UISlider *slider = [[UISlider alloc] initWithFrame:frame];
[slider addTarget:self action:#selector(sliderAction:) forControlEvents:UIControlEventValueChanged];
If you define correctly frame, you can make all of your sliders align nicely in your UI.
When a slider action is carried through by the user, the sliderAction: method is called, which has an argument referring to the slider:
- (void)sliderAction:(UISlider* slider) {
...
}
so you know exactly which slider was actioned and this is generally enough to handle the action.
In any case, as I said, if you want to keep track of all the sliders, add them to a NSDictionary at the moment of creation:
[self.sliderDict setObject:newSlider forKey:#"nth-slider-name"];
You don't need new variables for each slider, because the scope of the UISlider instance you use in your newSlider method is limited to that method. Meaning the variable will be free for use once the program exits the method.
You should also pass which slider it is to that method, this can then be used to position it and to give the view a tag for later use:
-(void) loadInterface {
// Set up a frame
CGRect myFrame = CGRectMake(10.0f, 100.0f, 250.0f, 25.0f);
for (int i = 0; i < x; i++) {
[self newSlider:i]
// Retrieve info here about the slider and pass it to newSlider
}
}
-(void) newSlider:(int)sliderNumber {
UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, sliderNumber * 100, 320, 50)];
slider.tag = sliderNumber;
[self.view addSubview:slider];
}

Specific action for each buttons in UIScrollView

I have an UIScrollView page . On this UIscrollView I have different images inside buttons you can see it in below code, and I want to load this images in UIWebView when I press the buttons, My question is how can I know which button are click. Would you please give me some hint for implementing this?
I'm new to objective-C
Here is my action: I want to have one action for each images, rightnow I have just one action for all images, I one to have one for each image
- (IBAction)openAction:(id)sender {
NSLog(#"test");
}
The actual button is passed to the IBAction. Setting a tag on the button is one way of doing it. If you created outlets for all your buttons in Interface Builder, you can simply do something like this:
- (IBAction)openAction:(id)sender {
UIButton *b = (UIButton *)sender;
if ([b isEqual:self.outletButton1]) {
// Do something with button 1
}
else if ([b isEqual:self.outletButton2]) {
// Do something with button 2
}
}
Don't use Same Tag for Button. Use Different Tag for different button.
For ex [btn setTag:1] .
you can use [btn setTag:i];
Dynamic value
Give each button a unique tag, in your code or in Interface Builder.
Then in your action you can do:
- (IBAction)openAction:(id)sender {
UIButton *b = (UIButton *)sender;
NSLog(#"button %d is pressed", b.tag);
}
I see that you already give your imageviews tags. Those are not buttons! You should instead create UIButtons whose content are images. See UIButton's setImage:forState:
Edit: In response to your question below, here's an example:
NSMutableArray *bArray = [NSMutableArray arrayWithCapacity:kNumImages];
NSUInteger i;
for (i = 1; i <= kNumImages; i++)
{
NSString *imageName = [NSString stringWithFormat:#"image%d.jpg", i];
UIButton *btn = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
btn setImage:imageName forState:UIControlStateNormal];
btn.tag = 100+i;
[bArray addObject:btn];
}
You don't have to add UIButton over UIImageView. Instead, you can set the image for UIButton like this.
[btn setImage:[UIImage imageNamed:#"image1"] forState:UIControlStateNormal];
You can access the image in the action like this:
- (IBAction)openAction:(id)sender {
if([[btn currentImage] isEqual:[UIImage imageNamed:#"image1"]]){
}
NSLog(#"test");
}

how to modify the properties of a button knowing its name and tag? (objective c)

What would be the code to modify the properties of a button (that was created programmatically) knowing its name and tag. (the amount of buttons created isn't always the same, that's why i assigned a tag to the buttons created)
You could use viewWithTag:
UIButton *btn = (UIButton*)[self.view viewWithTag:1];
//then change the properties
[btn setTitle:#"Press Me" forState:UIControlState];
//etc etc
The advantage of this is that if you have multiple buttons with the same changes you can easily loop through the different buttons
for (int i=0; i<numberOfButtons; i++) {
UIButton *btn = (UIButton*)[self.view viewWithTag:i+1];
[btn setTitle:#"Press Me" forState:UIControlState];
//etc etc
}
This assumes your tags start from 1 and increment.
All you really need to identify a button is its tag. The code would look something like:
if (button.tag == 2) {
button.titleLabel.text = #"New text";
button.enabled = NO;
// etc...
}
Merely place that into whatever function you want to change your button(s) in.

UISegmentedControl event does not work properly

I am currently working with a UISegmentedControl with 2 selections here. I have already defined it in -(void)viewDidLoad:
_segmentSelector = [[UISegmentedControl alloc] initWithItems:_selectorItems];
_segmentSelector.frame = CGRectMake(40, 356, 200, 43);
_segmentSelector.segmentedControlStyle = UISegmentedControlStyleBezeled;
_segmentSelector.selectedSegmentIndex = 0;
[_segmentSelector addTarget:self
action:#selector(selectorValueChanged)
forControlEvents:UIControlEventValueChanged];
The action for #selector(selectorValueChanged) is as following:
- (void)selectorValueChanged
{
if(_segmentSelector.selectedSegmentIndex=1)
{
}
if(_segmentSelector.selectedSegmentIndex=0)
{
}
}
My problem is, that when i run a simulation and clicked on one button, then attempted to click another button, the SegmentedControl does not respond. It stays on the selection and refuses to accept another tap/click/whatever action i ordered it to. What is wrong with it?
In selectorValueChanged, you assign new values to the selected segment index:
if (_segmentSelector.selectedSegmentIndex = 1)
Your probably mean
if (_segmentSelector.selectedSegmentIndex == 1)