iOS Button action doesn't work - ios

I have a strange issue with iOS UIButton.
I have a UIViewController class:
#interface CustomViewController : UIViewController
Inside of this class I have a label called customLabel. In this label I have a button subview:
UIButton *addButton = [[UIButton alloc] init];
[customButton setImage:[UIImage imageNamed:#"image"] forState:UIControlStateNormal];
[customButton addTarget:self action:#selector(customButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[customLabel insertSubview:customButton atIndex:1];
And of course, action method:
- (void)customButtonClicked
{
NSLog(#"- (void)customButtonClicked");
}
I also have a subclass for this view controller:
#interface MyNewCustomViewController : CustomViewController
This view controller is loaded inside UIWindow:
[self.navigationController pushViewController: myNewCustomViewController animated:YES];
Everything seems to be fine, label with button are at the correct positions, except the fact, that button click doesn't call action method...
Maybe you know, where the problem could be?

As long as you don't have another view over top of your current button and user interaction is enabled on the view. This should work.
// First make sure userInteractionEnabled is enabled for your custom label which will contain your button as a subview
customLabel.userInteractionEnabled = YES;
// Then create and add your button as a subview
UIButton *addButton = [[UIButton alloc] init];
[customButton setImage:[UIImage imageNamed:#"image"] forState:UIControlStateNormal];
[customButton addTarget:self action:#selector(customButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[customLabel addSubview:addButton]; // Places view on top index

Related

How to make buttons that go to a different screen?

Hey I'm having a lot of trouble with this idea I have. How do I make buttons that go to a different screen but on the CODE?
Basically depending on a value that may or may not be different for every user (Let's say the value is in x already) it will make a list of buttons...
When you click the list of buttons, they each individually go to a different screen.
How do I do this? I know how to on storyboard.. but code wise?
Edit: I SHOULD note that for the buttons specifically I have this and it is working in the code (didn't use storyboard):
UIButton * btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(50, 200, 200, 50);
[btn setTitle:#"Button 1" forState:UIControlStateNormal];
[self.view addSubview:btn];
First add a target to your button:
//Add target to your button, to call a method that presents the next ViewController:
UIButton *yourButton = [[UIButton alloc]init];
[yourButton addTarget:self action:#selector(goToNextPageMethod) forControlEvents:UIControlEventTouchUpInside];
User one of the two, case you are using a UINavigation controller or not, place them in the method you are calling when the button is pressed (the target)
//Normal presentation
YourViewController *vc = [[YourViewController alloc]init];
[self presentViewController:vc animated:YES completion:nil];
//Navgiation bar
YourViewController *vc = [[YourViewController alloc]init];
[self.navigationController pushViewController:vc animated:YES];
Hope this helps
You can attach an action to your button by doing the following:
UIButton * btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(50, 200, 200, 50);
[btn setTitle:#"Button 1" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(someAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
and then in your someAction method, you push the view modally or via your navigation controller
- (void)someAction
{
//init your view controller here....
YourViewController *vc = [[YourViewController alloc]init];
[self.navigationController pushViewController:vc animated:YES];
}

Modal View Controllers - UIBarButtonItems Do Not Persist

I present modal view controllers, packaged in a UINavigationController.
When they first appear, the bar button items are alright.
However, if I click a button and a new view controller is pushed to the UINavigationController, and then I use the back button of that view controller, and it gets popped back to the original modal view controller, the buttons do not show up, (but they work when I click them -> just can't see them)
I can't seem to figure out why this occurs.
Here's some code.
Oh, and by the way, I customize the navigation controller's navigation bar's background. I have a feeling this may be causing this visual interference, but I don't know what to change to get it right.
In GGMainViewController:
GGSelectTeamsViewController *chooseTeam = [[GIFSelectTeamsViewController alloc] init];
UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:chooseTeam];
[self setupModalNavigationBar:navigationController];
[self presentViewController:navigationController animated:YES completion:nil];
- (void)setupModalNavigationBar:(UINavigationController *)nav {
// unnecessary code removed for a quicker read
// basically navigation bar has a background gradient as well as a bottom border
[nav.navigationBar.layer addSublayer:bottomBorder];
[nav.navigationBar.layer addSublayer:gradient];
}
In GGSelectTeamsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
title = [[UILabel alloc] init];
title.text = someText;
title.backgroundColor = [UIColor clearColor];
title.textColor = [UIColor whiteColor];
self.navigationItem.titleView = title;
[title sizeToFit];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
[backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
backButton.frame = someFrame;
[backButton addTarget:self action:#selector(goBack) forControlEvents:UIControlEventTouchUpInside];
[self.navigationItem setLeftBarButtonItem:[[UIBarButtonItem alloc] initWithCustomView:backButton] animated:NO];
UIButton *selectButton = [UIButton buttonWithType:UIButtonTypeCustom];
[selectButton setTitle:#"Select" forState:UIControlStateNormal];
[selectButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
selectButton.frame = someFrame;
[selectButton addTarget:self action:#selector(sendContent) forControlEvents:UIControlEventTouchUpInside];
[self.navigationItem setRightBarButtonItem:[[UIBarButtonItem alloc] initWithCustomView:selectButton] animated:NO];
}
Since the navigation items are set in the viewDidLoad method, why can't I see them (but they are still functional) when I return to it from another view controller?
That seems like an over-complicated way of doing this.
Why don't you create your own button and then use the setRightBarButtonItems:items: method from the UINavigationBar to set the buttons you want?
I'm guessing they disappear because you're adding them to the layer of the UINavigationBar.
Still, if you want to keep this method with the layers, you may want to add them in the viewWillAppear method, but you may need call the removeFromSuperlayer to make sure you don't add stuff more than once.
Hope this helps.
The problem was:
the gradients for the navigation bar (done by code)
The solution was:
use Sketch to create an image of the gradients and use the appearance proxy to set the image as a background image
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"NavigationBarBackground"] forBarMetrics:UIBarMetricsDefault];

How to create re-usable code in iOS for a custom back button

I have created a custom back button (code below). I've so far been re-pasting this block of code all through my app on every single page. I was wondering if someone could take my code as an example and give me pointers on how to throw this into one centralized location so that I wouldn't have to copy and paste it anymore.
I'm guessing this would go into a custom class .h and .m that I'd create but I'm not exactly sure what to do next as far as what the code itself would look like within the custom files.
// Create custom back button
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *backButtonImage = [UIImage imageNamed:#"back.png"];
[backButton setBackgroundImage:backButtonImage
forState:UIControlStateNormal];
[backButton addTarget:self
action:#selector(backButton)
forControlEvents:UIControlEventTouchUpInside];
[backButton setFrame:CGRectMake(0, 0, 40, 40)];
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
[[self navigationItem] setLeftBarButtonItem:backButtonItem];
I would probably go with a category on UIViewController, with an interface like this:
#interface UIViewController (MyBackButton)
- (void)installBackButtonWithAction:(SEL)action;
#end
The implementation is the code from your question, with #selector(backButton) replaced by action:
#import "UIViewController+MyBackButton.h"
#implementation UIViewController (MyBackButton)
- (void)installBackButtonWithAction:(SEL)action {
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *backButtonImage = [UIImage imageNamed:#"back.png"];
[backButton setBackgroundImage:backButtonImage
forState:UIControlStateNormal];
[backButton addTarget:self
action:action
forControlEvents:UIControlEventTouchUpInside];
[backButton setFrame:CGRectMake(0, 0, 40, 40)];
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
[[self navigationItem] setLeftBarButtonItem:backButtonItem];
}
#end
You might call it like this, for example:
- (void)viewDidLoad {
[super viewDidLoad];
[self installBackButtonWithAction:#selector(backButton)];
}
You could create a subclass of UINavigationController and have it be alter the navigationItem of any view controller that's pushed Ito its stack to set the custom back button. Then you just create an instance of your custom class instead of your current use of UINavigationController and every view controller will automatically get updated.
You could put that code into a category somewhere; given you're setting self as the target, `UIViewController might work. But, thats kind of ugly and relies on an assumption that your dismissal action will never change.
Something cleaner that you could do is refactor it a bit so that you create the button by passing in the target (self) and dismissal action (backButton) and have the category on UIBarButton instead.

Make UIButton act as navigationcontroller

How can I make a regular UIButton act as a navigationcontroller so that when it's pressed I can open up a new view?
Create yourButton in viewDidLoad method as following way...
UIButton *yourButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[yourButton setTitle:#"YearButton" forState:UIControlStateNormal];
yourButton.frame = CGRectMake(240, 40, 75, 30);
[yourButton addTarget:self action:#selector(buttonSelected:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:yourButton];
This is your method code and createViewController which is object of CreateViewController class and it is declared in .h file.....
-(void) buttonSelected:(id)sender{
if (!createViewController) {
createViewController = [[CreateViewController alloc] initWithNibName:#"CreateViewController" bundle:nil];
}
[self.navigationController pushViewController:createViewController animated:YES];
}
I think it will be helpful to you.
Assuming you are using a UINavigation controller in your project.
then for the buttons action just call
[yourUIButton addTarget:self action:#selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
and for the method that gets called just do the following:
-(void)buttonAction{
[self.navigationController pushViewController:YourViewController animated:YES];
}

UINavigationController not popping view on back button

I have a UINavigationController. I've got a UIViewController that I've pushed onto the stack using pushViewController. The previous view controller has a backBarButtonItem simply titled "Cancel."
While the new view animates in correctly, when I tap Cancel, the navigation bar animates as if the view was popped, but the new view doesn't go away. Do I need to implement a delegate somewhere?
Try this,
First Create a UIButton then Create one UIBarButtonItem with Custom view, considering UIButton as custom view for UIBarButtonItem.
Consider button to target event for popping view controller.
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 35, 35);
[button setImage:[UIImage imageNamed:#"dots.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(backBarButton:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backBarButton = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = backBarButton;
- (void)backBarButton:(id)sender {
NSLog(#"%s", __FUNCTION__);
self.navigationController.navigationBarHidden = YES;
[self.navigationController popViewControllerAnimated:YES];
}

Resources