Subclassing UIView/UIViewController - ios

I need a lot of custom buttons in my app. At the moment I'm using storyboard to define these buttons on every controller that I need. However, I feel that since I need them throughout my app, I'm better off putting in a different view controller/view that subclasses UIView or UIViewController so if I need to make any changes I will just have to do them once as opposed to in different view controllers. What would be the best way to do this? Also can you tell me how can I create buttons programatically? This is what I'm doing at the moment, and I'm getting a completely blank screen.
-(void)viewDidAppear:(BOOL)animated
{
UIButton *testButton = [UIButton buttonWithType:UIButtonTypeCustom];
[testButton setFrame:CGRectMake(0, 390, 100, 40)];
[testButton setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin];
[setImage:[UIImage imageNamed:#"test_button"] forState:UIControlStateNormal];
[setImage:[UIImage imageNamed:#"test_button"] forState:UIControlStateHighlighted];
[setEnabled:YES];
[self.view addSubview:testButton];
}

there is a chance that your button is way off the visible rect. for adding the button programmatically, you are doing it mostly right. also, images should have the file extension. since you are adding a customButton, if there are no images, then you wont see any button. Try adding a title to your button, which would show up even if there is no image added.
try the code below.
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated]; //you must have a good reason to not add this line.
UIButton *testButton=[UIButton buttonWithType:UIButtonTypeCustom];
[testButton setFrame:CGRectMake(0, 20, 100, 40)];
[testButton setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin];
[testButton setImage:[UIImage imageNamed:#"test_button.png"] forState:UIControlStateNormal];
[testButton setImage:[UIImage imageNamed:#"test_button.png"] forState:UIControlStateHighlighted];
[testButton setEnabled:YES];
[self.view addSubview:testButton];
}

Related

UIButton Click Not working when its triggered from static library

We are trying to trigger display button from static library project using webview. while integrating static library with single view application we have got the output design. but when we tried to attempt action by clicking on Button its not working.
Below is the code,which we have used inside cocoa touch static library
UIButton *imageButton = [UIButton buttonWithType:UIButtonTypeCustom];
imageButton.frame = CGRectMake(self.view.frame.size.width-50, 10, 50, 50);
[imageButton setImage:[UIImage imageNamed:#"close.png"] forState:UIControlStateNormal];
imageButton.adjustsImageWhenHighlighted = NO;
// [imageButton addTarget:self action:#selector(close:) forControlEvents:UIControlEventTouchUpInside];
[imageButton addTarget:self action:#selector(hideWebViewBtn:) forControlEvents:UIControlEventTouchUpInside];
-(IBAction)hideWebViewBtn:(id)sender {
NSLog(#"Hide Button clicked");
[self.adView removeFromSuperview];
self.adView = nil;
return;
}
Below is the screenshot which displayed in single view application after integration and running.
Once i click on the button its not getting clicked.
try this,whether self button is triggering or not..
[self.myButton sendActionsForControlEvents:UIControlEventTouchUpInside];
It worked for me
You should add your button to a super view.And also,the super view should enable user interfaces.
[yourSuperView addSubView:button];yourSuperView.userInteractionEnabled=YES;
How about you change your return type of your 'hideWebViewBtn' method from 'IBAction' to 'void'?
"Once i click on the button its not getting clicked." You mean that u click the close button,but it doesn't call the function hideWebViewBtn:() ?
You can try this.
UIButton *imageButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width-100, 10, 50, 50)];
[imageButton setImage:[UIImage imageNamed:#"close.png"] forState:UIControlStateNormal];
[self.view addSubview:imageButton];
[self.view bringSubviewToFront:imageButton];
[imageButton removeTarget:self action:NULL forControlEvents:UIControlEventAllEvents];
[imageButton addTarget:self action:#selector(hideWebViewBtn:) forControlEvents:UIControlEventTouchUpInside];
Hope it works for you. Thanks!

UIButton programatically is not working in iOS

When I click on the UIButton nothing happened
checkbox = [[UIButton alloc] initWithFrame:CGRectMake(73, 324, 15, 15)];
[checkbox setBackgroundImage:[UIImage imageNamed:#"checkbox.png"] forState:UIControlStateNormal];
[checkbox setBackgroundImage:[UIImage imageNamed:#"checkbox-checked.png"] forState:UIControlStateSelected];
[checkbox addTarget:self action:#selector(autologin) forControlEvents:UIControlEventTouchUpInside];
[self.background addSubview:checkbox];
You have to create button like below.
UIButton *checkbox = [UIButton buttonWithType:UIButtonTypeCustom]; // this is important
checkbox.frame = CGRectMake(73, 324, 15, 15)];
[checkbox setBackgroundImage:[UIImage imageNamed:#"checkbox.png"] forState:UIControlStateNormal];
[checkbox setBackgroundImage:[UIImage imageNamed:#"checkbox-checked.png"] forState:UIControlStateSelected];
[checkbox addTarget:self action:#selector(autologin) forControlEvents:UIControlEventTouchUpInside];
[self.background addSubview:checkbox];
You have to create the button first using button property and then give its frame.
If still its not working then self.background addSubview should be self.view addSubview.
What is self.background?
Your code is perfectly fine. You need to check the following .
check whether self.background is placed properly in your view heirarchy, I tried your code with self.view instead of self.background like below and it works perfectly.
self.checkbox = [[UIButton alloc] initWithFrame:CGRectMake(73, 324, 50, 50)];
[self.checkbox setBackgroundImage:[UIImage imageNamed:#"checkbox1.png"] forState:UIControlStateNormal];
[self.checkbox setBackgroundImage:[UIImage imageNamed:#"checkbox2.png"] forState:UIControlStateSelected];
[self.checkbox addTarget:self action:#selector(autologin) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.checkbox];
From the error message that you have given
"
Warning: Attempt to present <enter_the_den: 0x7fbf1bd4c4e0> on <ViewController: 0x7fbf1bc771c0> whose view is not in the window hierarchy!
I suspect the issue is in your code inside the method autologin, just comment all the code in your method and just try a log , it should work.
refer this : whose view is not in the window hierarchy
If you read the Apple Documentation for UIButton and look under the heading marked as Creating Button you'll find that the way to create a UIButton is to use buttonWithType: and not initWithFrame:.
Return Value
A newly created button.
Discussion
This method is a convenience constructor for creating button objects with specific configurations. If you subclass UIButton, this method does not return an instance of your subclass. If you want to create an instance of a specific subclass, you must alloc/init the button directly.
When creating a custom button—that is a button with the type UIButtonTypeCustom—the frame of the button is set to (0, 0, 0, 0) initially. Before adding the button to your interface, you should update the frame to a more appropriate value.
The only time when you should use alloc/init with a UIButton is when you have subclassed UIButton however your init method should then implement the buttonWithType: and pass in UIButtonTypeCustom.
So change:
checkbox = [[UIButton alloc] initWithFrame:CGRectMake(73, 324, 15, 15)];
To
// Create a button of type custom
checkbox = [UIButton buttoWithType:UIButtonTypeCustom];
// Now set the frame for your button
[checkbox setFrame:CGRectMake(73, 324, 15, 15)];
// Continue with the rest of your button code
[checkbox setBackgroundImage:[UIImage imageNamed:#"checkbox.png"] forState:UIControlStateNormal];
[checkbox setBackgroundImage:[UIImage imageNamed:#"checkbox-checked.png"] forState:UIControlStateSelected];
[checkbox addTarget:self action:#selector(autologin) forControlEvents:UIControlEventTouchUpInside];
[self.background addSubview:checkbox];
Check userInteractionEnabled property of your background property.
But i see why you have no feedback on button if rest is fine - you use UIControlStateSelected for setting image when button has touch, but you must use UIControlStateHighlighted

How can I disable the multiple user interactions on a screen at a same point of time

In my application contains no.of UIElements like facebook button, twitter button, logout button, imageview with gestures.
`
facebookBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[facebookBtn setImage:#"facebook.png"];
[facebookBtn addTarget:self action:#selector(switchToFacebookShare) forControlEvents:UIControlEventTouchUpInside];
[facebookBtn setFrame:CGRectMake(0, 50, 24, 24)];
[self.view addsubview:facebookBtn];`
`twitterBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[twitterBtn setImage:#"facebook.png"];
[twitterBtn addTarget:self action:#selector(switchToTwitterShare) forControlEvents:UIControlEventTouchUpInside];
[twitterBtn setFrame:CGRectMake(0, 100, 24, 24)];
[self.view addsubview:twitterBtn];`
`imageTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(sectionTapping:)];
[imageTapGesture setNumberOfTapsRequired:1];`
`sectionPortraitImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[sectionPortraitImageView setUserInteractionEnabled:YES];
[sectionPortraitImageView addGestureRecognizer:imageTapGesture];
[contentView addSubview:sectionLandscapeImageView];`
like this i have added all the elements
When user click on all buttons at a time all three functionalities are working.
Here only one operation has to be done.
How can I solve this problem?
To Handle multiple touch issue at a time and also set individual property
[sectionLandscapeImageView setExclusiveTouch:YES];
// To handle all subviews multiple touch user interactions
-(void)multipleTouchHandling
{
self.view.multipleTouchEnabled=NO;
self.view.exclusiveTouch=YES;
for(UIView* view1 in self.view.subviews)
{
if([view1 isKindOfClass:[UIButton class]])
{
UIButton* btnVw = (UIButton*)view1;
[btnVw setExclusiveTouch:YES];
}
}
}
I see a few ways out of this situation.
You keep strong links to each button, and make
[someButton setUserInteractionEnabled:NO]
for each element after user click someone. But it takes a lot of time and code
(i think better solution) Or you can just show the UIActivityIndicatorView on top of view to block all user interaction while you processing some data or make some other actions.

button on a map is not getting displayed?

In my app, I have a map view, I want to display a custom button on the map, if a place the button, it gets displayed but, if I place a background image for the image, it is not getting printed.
UIButton *customButton = [UIButton buttonWithType: UIButtonTypeCustom];
[customButton setBackgroundImage:[UIImage imageNamed:
#"Button_Default.png"]
forState:UIControlStateNormal];
[customButton setBackgroundImage:[UIImage imageNamed:
#"Button_Highlighted.png"]
forState:UIControlStateHighlighted];
[customButton setFrame:CGRectMake(60, 100, 200, 40)];
[self.view addSubview:customButton];
I have also tried changing the last line as
[mapView addSubview:customButton];
You have to make sure that you have the images added to your project, may be in resource folder & the file name you are using in your code should not be misspelled (quiet often people do typo mistakes like using keyword imagedNamed instead of imageNamed).

Simultaneous push ViewController

I have a "strange" issue with xcode5 and the new sdk.
I have a Navigation controller.
The root view controller has 2 buttons, both buttons are linked to an action that push a viewcontroller into navigation-controller's stack.
If I run this project on XCode5 and if I push both buttons simultaneous the navigation controller going "crazy" with the message: "nested push animation can result in corrupted navigation bar".
But if I try the same code with xCode4 the application work also if I push simultaneous.
Have I forgot something??
Is this a already known behaviour?
There are a way to fix this issue?
Thanks a lot
This is the simple sample code
'
-(void)viewDidLoad
{
[super viewDidLoad];
UIButton *BTN1= [UIButton buttonWithType:UIButtonTypeRoundedRect];
[BTN1 addTarget:self action:#selector(ACTION) forControlEvents:UIControlEventTouchUpInside];
[BTN1 setTitle:#"XXX" forState:UIControlStateNormal];
[BTN1 setFrame:CGRectMake(0, 100, 100, 100)];
UIButton *BTN2= [UIButton buttonWithType:UIButtonTypeRoundedRect];
[BTN2 addTarget:self action:#selector(ACTION) forControlEvents:UIControlEventTouchUpInside];
[BTN2 setFrame:CGRectMake(0, 200, 100, 100)];
[BTN2 setTitle:#"XXX" forState:UIControlStateNormal];
[self.view addSubview:BTN1];
[self.view addSubview:BTN2];
}
-(void)ACTION
{
FirstViewController *fi = [[FirstViewController alloc] init];
[self.navigationController pushViewController:fi animated:YES];
}`
To prevent the navigation stack from being corrupted when pressing 2 buttons simultaneously, it is best to set exclusive touch to the buttons you are working with. This way you can prevent multiple triggers of the button action and prevent multiple ViewControllers from being pushed to the stack and corruption to happen.
[yourButton setExclusiveTouch:YES];
Use button.exclusiveTouch = YES; on each of your buttons.
You will need to hook them up to UIButtons and set the property in viewDidLoad for example.

Resources