UIButton crashing app on touch - iphone

I have a navigationController which holds a view with some buttons, but when I press a button I get a EXC_BAD_ACCESS error. I can't think what I'm doing wrong as the target is set right. It crashes whether the the button is added programmatically or via IB.
Button Code:
UIButton *reportsButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
reportsButton.frame = CGRectMake(20, 100, 100, 50);
[reportsButton setTitle:#"Reports" forState:UIControlStateNormal];
[reportsButton addTarget:self action:#selector(reportsButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
Function button is trying to access:
- (void)reportsButtonTouched:(id)sender
{
NSLog(#"working");
}
Error:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); //EXC_BAD_ACCESS code=1
}
The function the button is trying to access exists.
Maybe it's something about the way the NavigationController functions that I'm not aware of, but I've done this before without any problems.
Thanks for any answers, I really do appreciate the help I've got from this site before.
EDIT: This is my AppDelegates didFinishLaunching incase that helps in any way.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *homevc = [[HomeViewController alloc] initWithNibName:#"HomeViewController" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:homevc];
[self.window addSubview:nav.view];
[self.window makeKeyAndVisible];
return YES;
}

Nothing in your code seems to point to any issues. Use this tutorial to make Xcode break on all exceptions. This will take you closer to the 'scene of the crime' rather than crash to main.

I was also getting this error; I had been programming using SpriteKit and implementing my buttons a certain way, and then when I went back to not using the framework, all of a sudden every button I implemented was causing a bad access error.
I found out that I was initializing my buttons in viewDidLoad, because I had been using didMoveToView, and I accidentally treated them as the same function (which to be honest I don't really have a firm grasp on what viewDidLoad actually does).
But when I did this:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
[self addButton];
}
return self;
}
- (void)addButton
{
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 45, 45)];
[button setTitle:#"CLICK" forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonPressed:)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:button];
}
- (void)buttonPressed:(UIButton *)button
{
NSLog(#"WORKED");
}
Everything worked out fine... So try that, if you're still having trouble.
Good luck!

Related

UIButton Crashes on Click

Okay, so this is pretty weird; before upgrading to the final GMseed of Xcode my buttons worked perfectly fine...
Now I can't even do them on a super simple scale without the program crashing on click.
The absolute most bizarre aspect is that it works SOME of the time, but like 85%, it just crashes; and when it does work, it'll crash after extensive use.
Here is my code (stripped down to the simplest button implementation I could think of):
#interface TESTViewController ()
{
UIButton *button;
}
#end
#implementation TESTViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self addButton];
[button addTarget:self action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchDown];
}
- (void)addButton
{
button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 80, 45)];
[button setTitle:#"CLICK" forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:button];
}
- (void)buttonPressed
{
NSLog(#"WORKED");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
TESTViewController *test = [[TESTViewController alloc] init];
[self.window addSubview:test.view];
return YES;
}
I've tried creating the button in the init function, viewDidLoad -- neither works consistently, though viewDidLoad seems to work a little more frequently...
I tried -(void) addButton:(UIButton*)button as well
Using:
[button addTarget:self action:#selector(buttonPressed:)
forControlEvents:UIControlEventTouchDown];
--No difference.
I am at a total loss. I tried looking it up here on the forums, but unfortunately most of it refers to programming with IBActions.
The error I get is bad access
So my guess is that when the button is clicked, it's not actually accessing the buttonPressed function but something else entirely... I have no clue as to why this would be the case...
Thanks for any help!
The problem is in your "didFinishLaunchingWithOptions" method. Here you are creating a local object which gets Deallocated i.e "TESTViewController *test = [[TESTViewController alloc] init]".
You should retain this object, so try making it a property and use "self.test = [[TESTViewController alloc] init]". It will work.
Also conventionally you should use rootViewController rather adding your viewController to windows's subview.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.test = [[TESTViewController alloc] initWithNibName:nil bundle:nil];
self.window.rootViewController = self.test;
[self.window makeKeyAndVisible];
return YES;
}
I think you have a memory leak on that Button object are you using ARC or manual memory management? If manual make sure you retain it. If it is ARC use a property and the compiler will do the rest of the work
#property (nonatomic, strong) UIButton *button;
try it this way
- (void)addButton
{
button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 80, 45)];
[button addTarget:self action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"CLICK" forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:button];
}
and remove
[button addTarget:self action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchDown];
this line from viewDidLoad
I am not sure if this is the cause of the crash but actions (like your buttonPressed) should have a sender parameter:
[button addTarget:self action:#selector(buttonPressed:)
- (void)buttonPressed:(id)sender
{
...
}
To define a button programatically use the buttonWithType method, Try this
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(buttonPressed)
forControlEvents: UIControlEventTouchUpInside];//Any control event type
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, 80, 45);
[view addSubview:button];

UINavigationController not working under ARC in iPhone

I have created a new project "Empty Application" template in Xcode 4.3, it is having only two classes AppDelegate.h & .m
I checked with ARC to use automatic reference count while creating the app.
I added two new files "RootViewController" & "NewProjectViewControllers".
I implemented code to set navigation controller as follows in AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
rootViewController = [[MainViewController alloc] init];
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[self.window addSubview:navigation.view];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
and in hte home view (Root view controller) implemented as follows
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Projects";
UINavigationBar *navigationBar = [self.navigationController navigationBar];
[navigationBar setTintColor: [UIColor colorWithRed:10/255.0f green:21/255.0f blue:51/255.0f alpha:1.0f]];
//To set the customised bar item
UIButton *rightBarBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[rightBarBtn setBackgroundImage:[UIImage imageNamed:#"plus_new.png"] forState:UIControlStateNormal];
rightBarBtn.frame=CGRectMake(0.0, 100.0, 30.0, 30.0);
[rightBarBtn addTarget:self action:#selector(addProject) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem* rightBarItem = [[UIBarButtonItem alloc] initWithCustomView:rightBarBtn];
self.navigationItem.rightBarButtonItem = rightBarItem;
// Do any additional setup after loading the view from its nib.
}
- (void) addProject
{
NewProjViewController *editProject = [[NewProjViewController alloc] init];
[self.navigationController pushViewController:editProject animated:YES];
NSLog(#"xxxxxxxxxxxxxxx");
}
But since i used ARC the navigation may dealoc immediately and it doesn't work, All the actions in method works except push to the next view
if i do same thing with out ARC it works fine
How to resolve this issue..? Thanks in advance
In Your appdelegate appdidfinishlaunching method, you have not set
self.window.rootviewcontroller to navigationController. In fact you did not set any rootViewController to Window. Thats why it is not being shown. Please set it before you start to see your ViewController on the screen.
The UIWindow rootViewController property is new with iOS4.
The older technique was to use addSubview.
The new, recommended technique is to set rootViewController.
Try this:
NewProjViewController *editProject = [[NewProjViewController alloc]initWithNibName:#"NewProjViewController" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:editProject animated:YES];
[editProject release];

presenting modal on top of MPMoviePlayerController leads to crash, but only in iOS < 5.0

So, here's the situation (this is all in the simulator):
create a view controller. it owns an MPMoviePlayerController, and adds the player's view as a subview to its own.
set this vc as the window's rootViewController.
also in this vc's view is a button which will launch a modal view controller (which obscures the movie) after pausing the movie player.
click the button, launch the modal VC, then dismiss it.
notice that the paused image of the movie player is gone (it is just black).
click "play" to resume playing the movie
crash
Now, change your build target from iOS 4.3 to iOS 5.0 and it works flawlessly.
What's really bothering me is that this didn't cause a crash under 4.3 a month ago. In fact, I have an app in the store right now for which this works just fine: http://itunes.apple.com/us/app/es-musica-free/id474811522?mt=8
So, I've tried to boil this down to a minimal example which reproduces the problem.
Create a vanilla xcode project.
in your AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.backgroundColor = [UIColor blackColor];
[self.window makeKeyAndVisible];
UIViewController *vc = [[DemoMoviePlayerViewController alloc] init];
[self.window setRootViewController:vc];
[vc release];
vc = nil;
return YES;
}
DemoMoviePlayerViewController is pretty simple. here's the h file:
#import
#import
#interface DemoMoviePlayerViewController : UIViewController
{
MPMoviePlayerController *moviePlayer_;
}
#end
and the m file:
#import "DemoMoviePlayerViewController.h"
#interface DemoMoviePlayerViewController (InternalMethods)
- (void)_buttonPressed:(UIButton*)button;
#end
#implementation DemoMoviePlayerViewController
- (id)init
{
self = [super init];
if (self == nil)
{
return nil;
}
[self setWantsFullScreenLayout:YES];
NSURL *url = [NSURL URLWithString:#"http://once.unicornmedia.com/now/od/auto/0116d5af-bdc1-456d-a3ac-e3cbe25bac98/c762a821-e583-420c-b798-7b8c66736027/6c0e77e0-6dc4-48d5-9197-26e59271e8dd/content.once"];
moviePlayer_ = [[MPMoviePlayerController alloc] initWithContentURL:url];
return self;
}
- (void)dealloc
{
[moviePlayer_ stop];
[moviePlayer_ release];
moviePlayer_ = nil;
[super dealloc];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
[[self view] setBackgroundColor:[UIColor redColor]]; // debug
[[moviePlayer_ view] setFrame:[[self view] bounds]];
[[moviePlayer_ view] setAutoresizingMask:(UIViewAutoresizingFlexibleWidth
|UIViewAutoresizingFlexibleHeight)];
[moviePlayer_ setControlStyle:MPMovieControlStyleFullscreen];
[[moviePlayer_ view] setBackgroundColor:[UIColor greenColor]]; // debug
[[self view] addSubview:[moviePlayer_ view]];
// add a button to launch share kit
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"launch modal" forState:UIControlStateNormal];
[button addTarget:self
action:#selector(_buttonPressed:)
forControlEvents:UIControlEventTouchUpInside];
[[moviePlayer_ view] addSubview:button];
[button setFrame:CGRectMake(20, 100, 200, 40)];
[moviePlayer_ setShouldAutoplay:YES];
[moviePlayer_ play];
}
#pragma mark - internal methods -
- (void)_dismissModal
{
[self dismissModalViewControllerAnimated:YES];
}
- (void)_buttonPressed:(UIButton*)button
{
if ([moviePlayer_ currentPlaybackRate] == 1.0)
{
[moviePlayer_ setShouldAutoplay:NO];
[moviePlayer_ pause];
}
[self performSelector:#selector(_dismissModal) withObject:nil afterDelay:3.0];
UIViewController *vc = [[UIViewController alloc] init];
[[vc view] setBackgroundColor:[UIColor blueColor]];
[self presentModalViewController:vc animated:YES];
// yeah I know, vc is leaked...
}
#end
So apparently, somehow the MPMoviePlayerController is somehow able to detect which its view gets obscured, despite the fact that my view controller isn't doing anything fancy in viewWillDisappear or viewDidDisappear.
Again, what really bothers me is that, to the best of my knowledge, this worked just fine under 4.3 about a month ago.

Switching custom views programmatically (pushing and popping)

In iOS, my views work individually but I can't switch between them.
Now after a lot of google-ing around I've fond that the navigation based app would work great with the stack for views. The problem is all my views are nib/xib-less and custom tailored in the source code. Because of that I need my own UINavigationController and push and pop views by hand/code. Since every tutorial is either nib/xib and IB bound or just a mash of code snippets I need a concrete example how to do it.
A simple example with 2 programmatically created view (can be empty just have to use loadView instead of initializing with a nib/xib) and a working stack (a push and a pop of the views like: load app,create some root view if needed, push one view and from that view push the second one and then pop them) would be awesome, or at least a tutorial in that way with the whole source of the project and not snippets.
Thanks in advance.
EDIT: After some extra thinking, a little more clarification wouldn't be bad. My app will basically consist of 5 or 6 views which will be called form their respective previous view, i.e. a drill-down app.
Here's a brief code, only the essential parts:
CodeViewsPushingAppDelegate.m
#import "CodeViewsPushingAppDelegate.h"
#import "ViewNumberOne.h"
#implementation CodeViewsPushingAppDelegate
#synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
UINavigationController *navController = [[UINavigationController alloc] init];
ViewNumberOne *view1 = [[ViewNumberOne alloc] init];
[navController pushViewController:view1 animated:NO];
[self.window addSubview:navController.view];
[self.window makeKeyAndVisible];
return YES;
}
ViewNumberOne.h
#import <UIKit/UIKit.h>
#interface ViewNumberOne : UIViewController
{
UIButton *button;
}
- (void)pushAnotherView;
#end
ViewNumberOne.m
#import "ViewNumberOne.h"
#import "ViewNumberTwo.h"
#implementation ViewNumberOne
- (void)loadView
{
[super loadView];
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(110, 190, 100, 20);
[button setTitle:#"Push Me!" forState:UIControlStateNormal];
[button addTarget:self action:#selector(pushAnotherView) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
- (void)pushAnotherView;
{
ViewNumberTwo *view2 = [[ViewNumberTwo alloc] init];
[self.navigationController pushViewController:view2 animated:YES];
[view2 release];
}
ViewNumberTwo.h
#import <UIKit/UIKit.h>
#interface ViewNumberTwo : UIViewController
{
UILabel *label;
}
#end
ViewNumberTwo.m
#import "ViewNumberTwo.h"
#implementation ViewNumberTwo
- (void)loadView
{
[super loadView];
label = [[UILabel alloc] init];
label.text = #"I am a label! This is view #2";
label.numberOfLines = 2;
label.textAlignment = UITextAlignmentCenter;
label.frame = CGRectMake(50, 50, 200, 200); //whatever
[self.view addSubview:label];
}

Getting the view working in an App with no XIB

I've been trying to get a basic app working that doesnt use an XIB. It simply should load and draw a button.
At the moment the screen just appears white with apparently nothing on it.
In my delegate I pass across to my viewController Class.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[window addSubview:viewController.view];
[window makeKeyAndVisible];
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
return YES;
}
In my viewController class I implement loadview and viewDidLoad. Not sure if loadView is getting called. There is no XIB in this project.
-(void)viewDidload
{
[super viewDidLoad];
UIButton *singlePlayerButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect]
retain];
singlePlayerButton.frame = CGRectMake(50.0, 30.0, 100.0, 30.0);
[singlePlayerButton setTitle:#"Test" forState:UIControlStateNormal];
singlePlayerButton.backgroundColor = [UIColor blueColor];
[singlePlayerButton setTitleColor:[UIColor greenColor] forState:UIControlStateNormal ];
[singlePlayerButton addTarget:self action:#selector(playAction:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:singlePlayerButton];
}
-(void)loadView
{
NSLog(#"loadView");
UIView *view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen]
applicationFrame]];
self.view = view;
[view release];
}
Is there something I am missing?
I though this would be really quiet simple but after 2hrs of hitting my head against the wall nothing has changed.
Thanks -Code
Your viewDidload method has a case typo. It should be viewDidLoad (capital L).
Stupid suggestion perhaps, but where in the app delegate are you instantiating viewController?