UIButton click crashing app - ios

I have an error alert view that crash when I click "OK"
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitle:#"OK" forState:UIControlStateNormal];
[button setFrame:CGRectMake(10, 80, 266, 43)];
[button addTarget:self action:#selector(dismissError:) forControlEvents:UIControlEventTouchUpInside];
[alertView addSubview:button]; //This is a subview of
//...other stylings for the custom error alert view
errorWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
errorWindow.windowLevel = UIWindowLevelStatusBar;
errorWindow.hidden = NO;
[errorWindow addSubview:alertView];
[errorWindow makeKeyAndVisible];
}
This alertView is inside the custom ErrorAlert:UIView.
This alert shows up fine.
However, when click on "OK" button, app crashes, it never reached
- (void)dismissError:(id)sender;
Am I adding the button at the wrong place? (It gives the generic int retVal=......EXC_BAD_ACCESS)

You should not create a new UIWindow unless you're showing something on an external display.
In iOS, windows do not have title bars, close boxes, or any other visual adornments. A window is always just a blank container for one or more views. Also, applications do not change their content by showing new windows. When you want to change the displayed content, you change the frontmost views of your window instead.
Take a look at View Programming Guide for iOS

Related

iOS button frame incorrect on iPhone 6 simulator, works on iPhone 4s

In my view controller, my view is initialized in loadView method:
- (void)loadView
{
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self loadViewController];
[self.view setBackgroundColor:[UIColor whiteColor]];
}
The loadViewController method creates a button and adds it to the view. Here's a snippet from the loadViewController method that initializes and positions the button:
graphicalButton = [UIButton buttonWithType:UIButtonTypeCustom];
graphicalButton.exclusiveTouch = YES;
[graphicalButton setImage:kGraphicalIconSelected
forState:UIControlStateSelected];
[graphicalButton setImage:kGraphicalIconDeSelected
forState:UIControlStateNormal];
[graphicalButton setFrame:CGRectMake(230, 100, 37, 34)];
[graphicalButton addTarget:self
action:#selector(graphicalOptionAction:)
forControlEvents:UIControlEventTouchUpInside];
[graphicalButton setUserInteractionEnabled:NO];
NSLog(#"graphical button x %f",graphicalButton.frame.origin.x);
[self.view addSubview:graphicalButton];
This displays the button correctly on an iPhone 4s simulator. The log statement logs the origin correctly as well.
However, on an iPhone 6 simulator, the log statement always logs the origin.x as 0. The button does not get displayed if the code runs. If however, I set up a breakpoint at the beginning of this code snippet and then step through each line, it logs the origin.x correctly and the button is displayed even on an iPhone 6 simulator.
I have even tried adding the call to loadViewController in viewWillAppear method, but even there the same issue occurs with this button. Any ideas on why this happens and how to resolve this?

UIButton retains the glows after it has been touched

Hi i am making customUIButtons in my app by using the following piece of code.
+ (NSArray *) createButtonItemNormalImage:(UIImage *)normalImage
highlightImage:(UIImage *)highlightImage
disabledImage:(UIImage *)disabledImage
touchUpSelector:(SEL)selector
target:(id)target
{
// HighlightImage is not used. Highlight is shown using iOS glow
UIButton *uiButton = [UIButton buttonWithType:UIButtonTypeCustom];
uiButton.bounds = CGRectMake(0,
0,
normalImage.size.width,
normalImage.size.height);
[uiButton setImage:normalImage
forState:UIControlStateNormal];
if (disabledImage)
{
[uiButton setImage:disabledImage
forState:UIControlStateDisabled];
}
[uiButton addTarget:target
action:selector
forControlEvents:UIControlEventTouchUpInside];
uiButton.showsTouchWhenHighlighted = YES;
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithCustomView:uiButton];
return [NSArray arrayWithObjects:buttonItem, uiButton, nil];
}
I have made a cancel button using the above function. The cancel button takes the user from one screen to another screen. The problem is when i come back to the first screen the cancel button is still glowing. I have seen this problem before also but a call to [self.view setNeedsLayout] used to solve it.
Why does it happen and what would be a correct way of solving it?
Thanks!
To solve this problem in not so standard way I now set the highlighted state to no for all the buttons when I enter the first screen. I use myButton.highlighted = NO;. However the documentation says following for highlighted property.
Specify YES if the control is highlighted; otherwise NO. By default, a control is not highlighted. UIControl automatically sets and clears this state automatically when a touch enters and exits during tracking and when there is a touch up.
Its not happening so in my case.I would love to know the reason behind it and standard ways of solving it

Popover Control Background Color Odd Behavior

So in my app I have a popover control with an embedded navigation control. In different parts of the navigation stack, I want the popover to be different colors depending on where the user is. The weird thing is sometimes setting the popover background color makes this terrible looking box around it, sometimes it doesn't. It looks like this:
This is the look I am trying to get:
It seems if I change the background color before displaying the popover it seems to work and transition correctly, but if I don't set the popover color before showing it, then change it after it has been shown it has the box effect. I've also noticed other cases where it seems to happen randomly, but I can't really explain what is causing it (my real app is much more complex than this demo). Here is the relevant code:
- (IBAction)buttonPressed:(id)sender {
UIViewController *vc = [[UIViewController alloc] init];
UIButton *b = [[UIButton alloc] init];
[b addTarget:self action:#selector(innerButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[b setTitle:#"Button" forState:UIControlStateNormal];
[b setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[b setFrame:CGRectMake(0,0,100,100)];
[vc.view addSubview:b];
_innerNav = [[UINavigationController alloc] initWithRootViewController:vc];
_popOver = [[UIPopoverController alloc] initWithContentViewController:_innerNav];
//If this line is here, everything works fine
_popOver.backgroundColor = [UIColor yellowColor];
[_popOver presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
//If this line is here (and the above line is commented out), the transition will look wrong
//_popOver.backgroundColor = [UIColor yellowColor];
}
-(void)innerButtonPressed {
_controller = [[UIViewController alloc] init];
UIButton *b = [[UIButton alloc] init];
[b addTarget:self action:#selector(test) forControlEvents:UIControlEventTouchUpInside];
[b setTitle:#"Make Purple" forState:UIControlStateNormal];
[b setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[b setFrame:CGRectMake(0,0,200,200)];
[_controller.view addSubview:b];
[_popOver setBackgroundColor:[UIColor orangeColor]];
[_innerNav pushViewController:_controller animated:YES];
}
-(void)test{
_popOver.backgroundColor = [UIColor purpleColor];
}
Any idea what is causing this issue? And what steps to safely update the background color of a popover without ever getting into this state? I have a full project demonstrating the problem, I thought you could attach projects to questions but apparently you cannot. If someone wants it I can probably host it somewhere.
After looking at your sample project, Apple's "Popover Controllers in iOS" sample project, perusing Apple's Documentation, and trying a few different things I have come to the following observations:
The UIPopoverController only exhibits this odd behavior when it is presented without a valid value for the backgroundColor property. From this I am guessing that since UIPopoverController's backgroundColor property is nil by default it must use different drawing code than when the backgroundColor property is valid.
Triggering some sort of redraw (e.x. Setting popoverContentSize) will get the colored box overlay to go away (it looks like it clips a color layer).
Conclusion: For the time being I would set a backgroundColor prior to the UIPopoverController being presented and then update it as needed. If this is not an option try updating the UIPopoverController such that it redraws (As a note: I was not able to get this to look good and it seems hacky). Lastly, I would report it as a bug to apple.
I hope this helps.
UIPopoverController is now deprecated. I found a similar issue when updating it to use the new popoverPresentationController. In the past I was able to set the backgroundColor of UIPopoverController before presenting. The popover presentation controller also has a backgroundColor property but didn't work like it did before where I could assign it before presentation. To get it to work I had to assign it after it starts presenting for some reason:
contentViewController.modalPresentationStyle = UIModalPresentationPopover;
[[self presentViewController:contentViewController animated:YES completion:^{
// completion code
}];
contentViewController.popoverPresentationController.backgroundColor = [UIColor orangeColor];
For your particular scenario where you are changing the background color after presentation is finished I don't think you'd be able to do that by just changing the popoverPresentationController's backgroundColor. The only solution I can think of is to dismiss and re-present the popover without animating:
[self dismissViewControllerAnimated:NO completion:^{
contentViewController.modalPresentationStyle = UIModalPresentationPopover;
[[self presentViewController:contentViewController animated:NO completion:^{
// completion code
}];
contentViewController.popoverPresentationController.backgroundColor = [UIColor purpleColor];
}];

UIButton doesn't respond to touches

In my app, I need to parse some data from the network, and add some customized buttons.
Later, when user click on it, I would provide more details.
An image view is the background for the app
The position of these buttons(xPos, yPos) are parsed from the server(dynamic data)
no prints when I click on these buttons that I add programmatically
The code I have for adding it is like this
...
[businessButton setImage:businessImage forState:UIControlStateNormal];
[businessButton setFrame:CGRectMake([xPos floatValue], [yPos floatValue], [businessImage size].width/2, [businessImage size].width/2)];
[businessButton addTarget:self.imageView action:#selector(serviceProviderSelected:) forControlEvents:UIControlEventTouchUpInside];
...
- (void)serviceProviderSelected:(id)sender
{
NSLog(#"sp tapped\n");
}
I created another dummy app to do (what I think is the same thing), and the button works out fine...
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIButton *customizedButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [UIImage imageNamed:#"business-icon.png"];
[customizedButton setImage:image forState:UIControlStateNormal];
[customizedButton setFrame:CGRectMake(100, 100, 20, 20)];
[customizedButton addTarget:self action:#selector(customButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:customizedButton];
}
- (IBAction)buttonPressed:(id)sender {
NSLog(#"yes, pressed\n");
}
I've been suspecting that the buttons I create in code are already released, and printed out the array that I use for storing these Buttons, they are valid addresses though...
Thanks!
William
I just found out why.
Instead of [self.imageView addSubview:businessButton];, [self.view addSubview:businessButton]; works now.
I think I didn't really understand how the view relationship was after adding an imageView in storyboard.
UIImageView has user interactions disabled by default. you have to set this property to YES in order to get an UIButton or anything else working as it's subview
You need to do:
[businessButton addTarget:self action:#selector(serviceProviderSelected:) forControlEvents:UIControlEventTouchUpInside];
The target needs to be the class that defines the selector.

A UIButton above a UIPickerView

I have a UIPickerView which works correctly, now I want to add a button above it so that I can dismiss it.
and here is my code where I initiate a UIPickerView as well as its dismiss button:
- (UIPickerView *)creatPickerView {
UIPickerView *tempPickerView = [[[UIPickerView alloc]
initWithFrame:CGRectMake(kPickerViewX, kPickerViewY, kPickerViewWidth, kPickerViewHeight)] autorelease];
tempPickerView.showsSelectionIndicator = YES;
tempPickerView.delegate = self;
tempPickerView.dataSource = self;
UIButton *pickerButton = [[UIButton alloc] initWithFrame:CGRectMake(270, -32, 50, 32)];
[pickerButton setBackgroundImage:[UIImage imageNamed:#"hidePicker.png"]
forState:UIControlStateNormal];
[pickerButton addTarget:self action:#selector(hidePicker)
forControlEvents:UIControlEventTouchUpInside];
[tempPickerView addSubview:pickerButton];
[pickerButton release];
[self.view addSubview:tempPickerView];
return tempPickerView;
}
and it works well on my iPhone 4.3 Simulator, like this:
apparently there is a button on the upper right of the pickerView,
problem is, when I run the app in my device - a 5.0.1 iPhone4 and a 4.2.1 iTouch, the button is missed like it has never been added to the pickerView.
Can anyone help me with this?
Thanks a lot and a lot!
I found the reason, it seems the png has some problem,
after I change another png, it comes up in the screen!
but the real problem is that I place the button outside of the pickerView which results in the button's untouchableness.
But anyway the pickure is only a small problem.

Resources