UIButton added to subview in separate class where to store the method - objective-c

In a program, I have a class called PullLeftMenu.h/.m.
In ViewController.m I am calling the PullLeftMenu like so:
PullLeftMenu *openMenu = [[PullLeftMenu alloc] init];
[openMenu classMethodHere];
So, simply runs a method with arguments. However, a part of this method of class PullLeftMenu is adding buttons to a subview that appears. Each button is assigned its own method to be called. Say for examples sake, button 1 calls method btnUsefulStuff.
I have put btnUsefulStuff method code in both the PullLeftMenu class and in the ViewController.m, and neither are being triggered - instead causing a memory crash.
Code for a button in PullLeftMenu.m
UIButton *btnUsefulStuff = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnUsefulStuff.frame = CGRectMake(10.0, 180.0, 160.0, 10.0);
[btnUsefulStuff setTitle:#"Useful Stuff" forState:UIControlStateNormal];
[btnUsefulStuff addTarget:self action:#selector(btnUsefulStuff) forControlEvents:UIControlEventTouchUpInside];
btnUsefulStuff.titleLabel.font = [UIFont fontWithName:#"KhmerUI" size:16];
btnUsefulStuff.titleLabel.textColor = [UIColor colorWithHexString:#"3a589b"];
[secondView addSubview:btnUsefulStuff];
And below this is the method:
-(void)btnUsefulStuff{
NSLog(#"button");
}
Problem is, I dont know where to place the method -(void)btnUsefulStuff as wherever I place it, it doesnt seem to get triggered and the app crashes with a memory warning. Error is:
Thread 1: EXC_BAD_ACCESS

Since this line [btnUsefulStuff addTarget:self action:#selector(btnUsefulStuff) forControlEvents:UIControlEventTouchUpInside]; is in PullLeftMenu and you're saying the target is self, that's where your method needs to be.
I suspect your problem is that you've made openMenu a local variable. Change it to a strong property inside ViewController so that it's still in memory when someone taps the button.

Related

How to add an action to a UIButton

I've been searching online for this answer, and every single post skips over the part of where to actually write the code for an action. I have a simple Interactive UIButton. And If i could just see a template of code that says "\write code for action here", that would be super helpful!!! ( it's for iPad IOS7 )
This is as far as I can get...
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(aMethod:)forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[view addSubview:button];
I think I understand that this is how to set up a potential action, but where do I write the actual code for the action itself?
I want to kind of expand more on what was answered here already, Both responses are correct but i want to explain why/how this all works.
[button addTarget:self
action:#selector(aMethod:)forControlEvents:UIControlEventTouchDown];
The first thing to look at; The target.
The target is the instance of a class, any class. The only requirement for this class is that it has to implement the action.
action is the method you wish to invoke when the user presses the button.
#selector(aMethod:) Basically think of this as a method signature. Because Objective-c is a dynamic language, aMethod: does not need to exist, but will crash your program if it does not.
So if we put this all together, Whenever I want to press this button:
The system will invoke the action method, on the target instance.
and for the method itself, it can look like this
- (void) aMethod:(id)sender { }
You would put the action related code in a method, in that class, named aMethod:
- (void)aMethod:(id)sender {
// your code for the action goes here
}
You perhaps might also want to use UIControlEventTouchUpInside for the control event.
Since you've set the target as self, the aMethod: method should be added to the same class.
- (IBAction)aMethod:(id)sender
{
// do something here
}

How do I add a method to a button I made programmatically?

I'm working with a pre-existing xcode project for an iPhone app that retrieves flickr pictures. I want to add a favorite button so that a user can add a photo to an array of favorites, but I'm stumped because I've never made UI objects programmatically before.
Here is the code for my button, but how would I add a method do it? Also, where would this method definition go?
// Create favorites button
UIButton *favButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
favButton.frame = CGRectMake(200, 50, 100, 50);
[favButton setTitle:#"Favorite" forState:UIControlStateNormal];
favButton.backgroundColor = [UIColor clearColor];
[favButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal ];
UIImage *buttonImageNormal = [UIImage imageNamed:#"blueButton.png"];
UIImage *strechableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[favButton setBackgroundImage:strechableButtonImageNormal forState:UIControlStateNormal];
UIImage *buttonImagePressed = [UIImage imageNamed:#"whiteButton.png"];
UIImage *strechableButtonImagePressed = [buttonImagePressed stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[favButton setBackgroundImage:strechableButtonImagePressed forState:UIControlStateHighlighted];
[favButton addTarget:self action:#selector(playAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:favButton];
Is the addTarget method the way to add a method? Because whenever I click the button, it sends me back to xcode and shows me the main.m file and highlights this line of code:
int retVal = UIApplicationMain(argc, argv, nil, nil);
Sorry, I'm totally new to this. The project has the following files:
JSONFlickrAppDelegate.h
JSONFlickrAppDelege.m
JSONFlickrViewController.h
JSONFlickrViewController.m
ZoomedImageView.h
ZoomedImageView.m
Here is the xcode project that I am working off of:
http://compsci.cis.uncw.edu/~pattersone/courses/275/resources/JSONFlickrPart3.zip
Yes, this is the method that adds the method:
[favButton addTarget:self action:#selector(playAction:) forControlEvents:UIControlEventTouchUpInside];
The method, however, that will be called is playAction:. Whatever is located after addTarget is simply the object that will call the method, in the case of self, it is the object where this button is being created that it rests inside.
Looks like there are some confusions with how you need to add a target to a method.
Is the addTarget method the way to add a method?
Yes, you are correct. addTarget method is the way to add a method associated with the button and the method definition should be written on the class which is mentioned as addTarget param(In this case self, which is an object of current class).
When you use this line,
[favButton addTarget:self action:#selector(playAction:) forControlEvents:UIControlEventTouchUpInside];
It means that you are adding a method named playAction: to button which should be executed in target self on the event of UIControlEventTouchUpInside i.e, when an event occurs as user taps inside the button. So the action playAction should be inside the class which is represented by the object self i.e, the class in which you have written the above [favButton addTarget:... line. You can add any number of targets to this same button using similar addTarget lines.
but how would I add a method do it? Also, where would this method
definition go?
In this scenario, you need to define the method playAction: in the same class since you added target as self. This can be changed to any object of any class and the method can be written in that class.
for eg:-
- (void)playAction:(id)button {
//write the required code here, button is same as the favbutton which is written above.
}
Because whenever I click the button, it sends me back to xcode and shows me the main.m
file and highlights this line of code:
The reason why it is going back to xcode and shows the main.m is because it is a crashing since you haven't provided any playAction: method in your class. Since it cannot find any such method in the target self, it will crash and sometimes it just point to the main.m class.
You can also add target as follows,
[favButton addTarget:self action:#selector(playAction) forControlEvents:UIControlEventTouchUpInside];//notice that it is 'playAction' and not 'playAction:' with a colon at the end.
In this case your method will look like,
- (void)playAction {
//write the required code here
}
These are just different ways to do this.
For more details, please check this apple documentation.

How to move an image with a button?

I have an image(clubcow.png) that is passed from an nsarray string to make a picture. Then facedowncow represents the picture. I was wondering how to make a button that will move facedowncow to position (100,100) when button is tapped. Any tips will be appreciated. Also, there is more to this code, I just posted the important parts to give an idea on what is going on.
cardKeys = [[NSArray alloc] initWithObjects:#"clubcow", nil];
currentName = [NSMutableString stringWithFormat:#"%#.png", [cowsShuffled objectAtIndex:currentcow]];
faceDowncow = (UIImageView *)[self.view viewWithTag:1];
faceDowncow.userInteractionEnabled = YES;
I would start by creating a UIButton and adding it to your view controller's view.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(0, 0, 100, 20);
[button setTitle:#"Tap Me" forState:UIControlStateNormal];
[button addTarget:self action:#selector(animateImage:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
Then, link this button to a function that will animate your faceDowncow object. You could add your faceDowncow as a property of the view controller so the following function can easily reference it:
- (void)animateImage:(UIButton *)sender {
[UIView animateWithDuration:0.2
animations:^{
// change origin of frame
faceDowncow.frame = CGRectMake(100, 100, faceDowncow.frame.size.width, faceDowncow.frame.size.height);
} completion:^(BOOL finished){
// do something after animation
}];
}
First of all, it looks like this code is from a view controller subclass, and the cow is a subview. In that case, you should probably have a property for it rather than obtaining it by its tag all the time. If it's instantiated in a storyboard scene/nib then you can hook up an outlet to a property/ivar in your subclass fairly easily.
The easiest way to do what you want is to create the button and use target action so that when it is tapped, it calls a method in your view controller. In the method body, obtain a reference to your cow and set it's frame property, like so:
[faceDowncow setFrame: CGRectMake(100,100,faceDowncow.bounds.size.width,faceDowncow.bounds.size.height)];
If you don't know how target action works, I suggest reading Apple's documentation on the matter. It's as simple as getting a button, calling one method to tell it what events should make a certain method get called, and then implementing that method.

objective-c accessing class variable from button selector

I am initializing UIButton in init method of a class like this:
UIButton* upButton=[[UIButton alloc] initWithFrame:CGRectMake(2*stepX, 13*stepY,2*stepX,stepY)];
[upButton setTitle:#"UP" forState:UIControlStateNormal];
[upButton setBackgroundColor:[UIColor blueColor]];
[upButton addTarget:self action:#selector(pressedUp) forControlEvents:UIControlEventTouchUpInside];
In pressedUp method I need to use variables from that class (NSInteger* and my class hero*).
So I am doing:
hero*h=self.mainHero;
NSInteger*m=self.map;
But later in code I can easily work with hero class (change position etc) but it fails to work with self.map (awful integers in array instead of 0 and 1)... How to fix it?
From your last comment it appears that the problem is due to a dangling reference: you create a local variable lvl1Map[], assign it to self.map, and exit the initializer. At this point, lvl1Map[] is gone, but the map is pointing to the area in the memory where it once has been.
You can fix this problem by declaring lvl1Map static:
NSInteger lvl1Map[]={...};
[self setMap:lvl1Map];

Creating/Displaying Interface Objects with Code for the iPhone [Objective-C]

I'm currently designing an app that calls for dynamically creating objects and then displaying them in a ViewController. My problem is wading through the documentation to try and create the objects I need. I've done some searching and even tried to just sit down and figure it out, but alas, I've got nothing to show for it. I already know how to dynamically create the ViewController but I can't seem to get any objects in it.
Does anyone know how I could go about creating objects (Say a button and a slider) dynamically with Objective-C in XCode?
Creating a button in code is simple
- (void)addButton {
// Create button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// Set the frame (location and size)
[button setFrame:CGRectMake(0, 0, 40, 30)];
// Set what happens when you touch the button
[button addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
// Set button text
[button.titleLabel setText:#"Button"];
// Add button to view
[self.view addSubview:button];
}
A lot of interface elements follow a similar patter- alloc and init the object, set the frame and add it to a view.