UIButtons not working on programmatically created UIView - iphone

I have a UIViewController which I want to display a UIView that renders as a menu. This menu will have several buttons on it. I wanted to reuse this menu a few different places in my app so I figured I would create a class called ViewFactory that has a method that returns a UIView with these buttons.
On my ViewController I call this method and get the returned UIView and add it as a subview.
This works just fine. I can see the view and all its buttons, however, the buttons do not respond to any touch events. Not sure why this is the case and curious to know what I am doing wrong.
Here is my code for the ViewFactoryClass:
- (UIView *) addCloseRow
{
// UIView container for everything else.
UIView *navRow = [[UIView alloc] initWithFrame:CGRectMake(0,225,350,45)];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.userInteractionEnabled = YES;
[navRow addSubview:button];
[button addTarget:self action:#selector(closeButtonTouchDownEvent) forControlEvents: UIControlEventTouchDown];
navRow.userInteractionEnabled = YES;
return navRow;
}
In my main NavigationController class here is how I am calling and getting the UIView:
ViewFactory *factory = [[ViewFactory alloc] init];
[self.navigationController.navigationBar addSubview:[factory MainNavigationUIView]];
Again, the UIView shows up but the buttons never respond to anything.

You added the button with target and selector for ViewFactoryClass
And now you are creating instance and trying to call an action from ViewFactory class.
You can change the method to something like this:
- (UIView *) addCloseRow : (id)object {
...
[button addTarget:[object class] action:#selector(closeButtonTouchDownEvent) forControlEvents: UIControlEventTouchDown];
...
}

Related

Custom UIButton's action does not called

I have subclass of UIButton:
#interface MyButton : UIButton
- (IBAction) buttonPressed:(id)sender;
#end
#implementation MyButton
- (void)awakeFromNib
{
NSLog(#"awake from nib");
}
- (IBAction) buttonPressed:(id)sender
{
NSLog(#"button pressed");
}
#end
I add a button in my parent xib, set it's class to MyButton, and connected it's action to First Responder's method buttonPressed.
When I start an application and load my parent xib with my button inside, than awakeFromNib from MyButton class is called. But when I press the button, nothing happens. I was expecting that my method buttonPressed from MyButton class will be called.
I supposed, that my button's view is the first responder in responder chain, but apparently I do something wrong.
Could you please suggest something?
If you want that your button always call the method declared add the code above to the awakeFromNib method
[self addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
and later when you added it to a view controller do not assign it a new action, this way it will always call your method.
Depending on what you are doing with the button - there is no real need to make a subclass.
Here is some code how to make a simple button that triggers a method:
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[myButton setFrame:CGRectMake(10, 10, 100, 30)];
[myButton setTitle:#"Title" forState:UIControlStateNormal];
[myButton addTarget:self action:#selector(myMethod:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:myButton];
the add target bit tells the button to trigger the given selector when the user touches up inside the button (taps it). The target is the object that the selector is in.
Hope this helps, you should not need to subclass UIButton unless you have custom layouts or specific custom functionality for it.
Since you want to handle the action from the button code itself, you may have to override this method - (void)sendActionsForControlEvents:(UIControlEvents)controlEvents and handle your event as if it was sent to your button;

ios : same ui controls across various screens in ios app

I am fairly new to iOS development. My requirement is I am designing an app that contains 5 screens . I have a set of UI controls( 1 UIImageView 5 UIButtons acting like tab bars for each screen) that are common for all the screens. When a button is clicked only the bottom half of the view needs to change with a relevant details while the buttons stay intact(similar to tab control in windows).
Is there a way to achieve this design? Can I share UI controls across multiple screens without repetition in code or
Is there a way to change only the bottom half of the screen when a button is clicked?
You could have a separate class that would create your UIControls and then for each viewcontroller you call the appropiate method to get the UIControls you want.
#interface UIControlMaker : NSObject{
id controlmakerDelegate; // This is so that you can send messages to the viewcontrollers
}
#property (nonatomic,retain) id controlmakerDelegate; // Release it in dealloc method
- (id)initWithDelegate:(id)delegate;
- (UIView *)createCommonUIControls;
In the implementation file
#implementation UIControlMaker
#synthesize controlmakerDelegate;
- (id)initWithDelegate:(id)delegate{
if(self = [super init]){
[self setControlMakerDelegate:delegate];
return self;
}else
return nil;
}
- (UIView *)createCommonUIControls{
UIView *uicontrolsHolder = [[UIView alloc] initWithFrame:CGRectMake(2,40,320,50)];
// Create as many uicontrols as you want. It'd be better if you have a separate class to create them
// Let's create a button for the menuItem
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0 , 0, 50, 35)];
button.backgroundColor = [UIColor clearColor];
[button setTitle:#"Button 1" forState:UIControlStateNormal];
[button addTarget:controlmakerDelegate action:#selector(buttonOnClick) forControlEvents:UIControlEventTouchUpInside];
[uicontrolsHolder addView:button];
[button release];
// Add more uicontrols here
retun [uicontrolsHolder autorelease];
}
Then in your viewcontrollers create an instance of UIControlMaker and call the createCommonUIControls method which will return a View that you can add to your viewcontroller. Hope that was clear.

Click through UIWindows

I've been following this example in everything to create a UIWindow on top of the statusBar.
My UIWindow gets displayed on top of the statusBar and all is fine, but the actual view of the app (the one with the button) doesn't respond to my actions:
I'm using Storyboards and iOS6.
Here's my code for creating a statusBar overlay:
- (void)viewDidAppear:(BOOL)animated {
UIWindow *overlayWindow = [[ACStatusBarOverlayWindow alloc] initWithFrame:CGRectZero];
AppDelegate *app = [[UIApplication sharedApplication] delegate];
overlayWindow.rootViewController = app.window.rootViewController;
app.window = overlayWindow;
[overlayWindow makeKeyAndVisible];
}
The view under the statusBar does not respond and I can't tap on the UIButton. Is it possible to somehow make the UIWindow with the interface of my app accept the touches ignoring the ACStatusBarOverlayWindow? How can that be done?
Usually if a button does not respond to a touch it's because the button is outside of the bounds of it's parent's UIView.
Your code does not seem to be the appropriate approach to the problem you're trying to solve. If you just need your window to have a status bar, or you just need to add a button to you current view, the way you're doing it is probably incorrect.
Personally I've never seen anyone instantiate a UIWindow in a viewDidAppear, since the app comes with it's own UIWindow. You should be using a UIView and adding your overlay to it.
As a side note if you were to do it the way you're attempting to, then your window would at least need a frame. So initWithFrame:CGRectZero would be initWithFrame:CGRectMake(0,0,320,480) or something along those lines.
A better way to approach the problem is to instantiate a UIViewController and set it as your rootViewController. Or simply add your button to the current viewController's view.
- (void)viewDidLoad {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(myMethod:)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Tap Me" forState:UIControlStateNormal];
[button sizeToFit];
[self.view addSubview:button];
}

UIViewController Problem with IB

This is what I do
Setup a view with UIViewController Subclass
Go to IB, and pull a view into the iphone
Pull a navigation bar over the UIView
Pull a tableview on the space below.
Everything appears well when I am running the interface builder.
But these things do not work.
If I add a button on top of the Navigation Bar, the button appears but IBAction is not called. The button seems to be at a level beneath the Navigation Bar (somewhere else)
If I add a footer view for the tableView, it does not appear. I believe the UIView is again masking it or something...
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UIView *viewForFooter = [[UIView alloc] init ];
UIButton *footerButton = [[UIButton alloc] initWithFrame:CGRectMake(200, 40, 100, 40)];
footerButton.titleLabel.text = #"Forgot Login";
//self.forgotLogin = footerButton;
[viewForFooter addSubview:footerButton];
return viewForFooter;
}
WHY ?
1) No reaction to click: Try to add the action in code. If it works, something was wrong with connecting up the IBAction.
[self.barButton setTarget:self];
[self.barButton setAction:#selector(IBActionHandler:)];
As a backup, you can also try to add the button in code:
UIBarButtonItem *barButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
selector:#selector(IBActionHandler:)];
self.navigationItem.rightBarButtonItem = barButton;
[barButton release];
2) Invisible button - I think your button is a custom UIButton, so it is transparent. The title is not visible because you have to set it like this:
[footerButton setTitle:#"Forgot Login" forState:UIControlStateNormal];
If you want a regular rounded angle button you have to set the frame after creating it.
UIButton *footerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// Careful, this button is autoreleased.
[footerButton setFrame:CGRectMake(200, 40, 100, 40)];
BTW, something might also be wrong with your CGRects. The footerView should perhaps also be properly initialized with a frame, and you might have to implement
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
as well.
PS: To go with a standard UITableViewController might actually be a good idea.
Happy coding!

Create UIView through code and add events in iphone

I have created a UIView and added label to it and latter assign it to Controller.
Now whenever I click on my View it shows me "EXC_BAD_ACCESS”.
Below is my code.
//create a UIView in App Delegate
UIView *viewPtr = [[[UIView alloc] initWithFrame:frmRect] autorelease];
//created a Button and added to UIView
UIButton *btnPointer = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnPointer.frame = cgframe; // provides both a position and a size
[btnPointer setTitle:btnLabelText forState:UIControlStateNormal];
[btnPointer addTarget:self action:#selector(generate:) forControlEvents:UIControlEventTouchUpInside];
[viewPtr addSubview:btnPointer];
//Now need to add this UIView to a controller
viewController.view = viewPtr;
I am able to display the button on the Form but when I click on the form or the button I get
"EXC_BAD_ACCESS”.
You should create the view in the .m file of your view controller like this.
- (void)loadView
{
UIView *viewPtr = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
//created a Button and added to UIView
UIButton *btnPointer = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnPointer.frame = cgframe; // provides both a position and a size
[btnPointer setTitle:btnLabelText forState:UIControlStateNormal];
[btnPointer addTarget:self action:#selector(generate:) forControlEvents:UIControlEventTouchUpInside];
[viewPtr addSubview:btnPointer];
//Now need to add this UIView to a controller
self.view = viewPtr;
[viewPtr release];
}
Hope this helps.
Thanks,
Madhup
Instead of use the autorelease
UIView *viewPtr = [[[UIView alloc] initWithFrame:frmRect] autorelease];
Create the UIView *viewPtr on the .h file, and only do the release in the dealloc method
So, you will have the declaration on your .h file
UIView *viewPtr;
And you .m file will be with the following lines, when you instantiate the viewPtr in the same place where you was doing previously, but without the autorelease, and the release on the dealloc method as follow:
viewPtr = [[UIView alloc] initWithFrame:frmRect];
.
.
.
.
.
.
.
.
- (void)dealloc {
[viewPtr release];
[super dealloc];
}
The autorelease is the main problem in your code, because when you do this, your UIView won't respond to any event.
Cheers,
VFN
What is self in [btnPointer addTarget:self ... ? Is generate: called? Have you tried debugging there?
As vfn says, this you get the error because you release the view too early. The question I would be asking is why is this case different?
Normally in an assignment like this:
viewController.view = viewPtr;
The viewPtr is retained and you would be correct to release it yourself. But look at the definition:
#property(nonatomic, retain) UIView *view
This means that any value is simply assigned and not automatically retained.