Why does my iOS app crash when trying presentModalViewController? - ios

I've been banging my head against this all day, it seems like something simple but I can't figure it out.
I've got an iOS app that I created using the "View-based Application" template in XCode. Here is essentially the code I have:
AppDelegate.h:
#import <UIKit/UIKit.h>
#interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MainViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet MainViewController *viewController;
#end
AppDelegate.m:
#import "AppDelegate.h"
#import "MainViewController.h"
#implementation AppDelegate
#synthesize window, viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
MainViewController.h:
#import <UIKit/UIKit.h>
#interface MainViewController : UIViewController {
}
-(IBAction) button:(id)sender;
#end
MainViewController.m:
#import "MainViewController.h"
#import "ModalViewController.h"
#implementation MainViewController
...
-(IBAction) button:(id)sender {
ModalViewController *mvc = [[[ModalViewController alloc] initWithNibName:NSStringFromClass([ModalViewController class]) bundle:nil] autorelease];
[self presentModalViewController:mvc animated:YES];
}
#end
There's nothing of interest in the ModalViewController.
So the modal view should display when the button is pressed. When I press the button, it hangs for a second then crashes back to the home screen with no error message.
I am stumped, please show me what I'm doing wrong!

There's nothing of interest in the ModalViewController.
Although there may not be anything of interest, there could still be something causing the problem.
Does your View Controller override the function loadView?
A problem that has got me a few times is if you don't call [super loadView]; first in your overriden loadView method. Not doing this causes a crash when moving into that View Controller.
Good luck in trying to solve this one!
N

Related

How to access tabBarController from AppDelegate.m?

This is my storyboard:
I am trying to access tabBarController from a method inside AppDelegate.m
This is AppDelegate.h:
#import <UIKit/UIKit.h>
#import <FacebookSDK/FacebookSDK.h>
#import "STAlertView.h"
#interface demo_AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, strong) STAlertView *av;
#end
And this is AppDelegate.m:
#import "demo_AppDelegate.h"
#import "demo_Friends_ViewController.h"
#implementation demo_AppDelegate
-(void)showFriendReqAlert:(NSNotification *)pNotification{
NSLog(#"Hello from showFriendReqAlert:");
NSLog(#"Root: %#", [self.window.rootViewController.navigationController.tabBarController viewControllers]);
}
....
....
....
....
#end
My main motive is when this method showFriendReqAlert: is called, a red badge is shown to the third tab bar item which is Friends. But whenever i try to select tabBarItem, it says null in NSLog.
I have also tried the following:
self.window.rootViewController.navigationController.tabBarController
self.window.rootViewController.tabBarController
but nothing works. Any help?
Thanks!
I believe (sorry for believing here ;-) that the TabBarController should be your first controller and your navigationBarController must come afterwards as it does not make much sense for the navigationController (if you change a tab) what to push/pop.
I suggest that you remove your first DemoViewController and following NavigationController and that your first Controller is your TabBarController (simply set "Is Initial View Controller" in IB).
Then you can access your tabBar like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UITabBarController *tbc = (UITabBarController *)self.window.rootViewController;
}
Swift 5:
guard let tabBarController = window?.rootViewController as? UITabBarController else { return }

NSInternalInconsistencyException error

I am having issues switching between view controllers.
My md360AppDelegate.h header looks like this
#import <UIKit/UIKit.h>
#class md360ViewController;
#interface md360AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) md360ViewController *viewController;
#property (strong, nonatomic) UINavigationController *navigationController;
#end
and my md360AppDelegate.m implementation looks like this.
#import "md360AppDelegate.h"
#import "md360ViewController.h"
#implementation md360AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[md360ViewController alloc] initWithNibName:#"md360ViewController" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.navigationController setNavigationBarHidden:YES animated:YES];
[self.window setRootViewController:self.navigationController];
[self.window makeKeyAndVisible];
return YES;
}
#end
i am creating an instance of UINavigationController and storing it in navigationController property of this class.
I want to change the ViewController when a user click on a button in md360ViewController.
My md360ViewController.h looks like this.
#interface md360ViewController : UIViewController
#property IBOutlet UIButton *homePathwayBtn;
#property IBOutlet UIButton *homeDiseaseBtn;
#property IBOutlet UIButton *homePipelineBtn;
- (IBAction)homeButton:(id)sender;
#end
and my implementation looks something like
#import "md360ViewController.h"
#import "md360AppDelegate.h"
#import "pipeViewDisease.h"
#import <QuartzCore/QuartzCore.h>
- (IBAction)homeButton:(id)sender {
UIViewController *pipeViewDisease = [[UIViewController alloc] initWithNibName:#"pipeViewDiease" bundle:nil];
[self.navigationController pushViewController:pipeViewDisease animated:YES];
}
and when i click on UIButton the application crash with following message.
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Could not load NIB in
bundle: 'NSBundle
(loaded)' with name 'pipeViewDiease''
what could be the issue?
Probably just a misspelled NIB name:
initWithNibName:#"pipeViewDiease"
should be:
initWithNibName:#"pipeViewDisease"
^
Unless it's a spelling mistake (should be pipeViewDisease), this error usually occurs when files are re-named outside of the xCode environment.
To fix this:
remove the file in question from the project
re-import the files to your project.

Basic error in iPad application launch

I have a file named MMAppDelegate.m:
#import "MMAppDelegate.h"
#implementation MMAppDelegate
#synthesize window;
#synthesize viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
viewController = [[MainViewController alloc] init];
[window addSubview:viewController.view];
// Override point for customization after application launch.
[window makeKeyAndVisible];
return YES;
}
//and more standard methods
MMAppDelegate.h:
#import <UIKit/UIKit.h>
#import "MainViewController.h"
#interface MMAppDelegate : UIResponder <UIApplicationDelegate> {
UIWindow *window;
MainViewController *viewController;
}
#property (nonatomic, retain) UIWindow *window;
#property (nonatomic, retain) MainViewController *viewController;
#end
MainViewController.m:
#import "MainViewController.h"
#implementation MainViewController
- (void)viewDidLoad {
NSLog(#"view did load main view controller");
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
}
#end
And yet when I run the program, I get a black screen, and the output:
2012-02-12 15:44:48.160 MoreMost[44076:f803] view did load main view controller
2012-02-12 15:44:48.163 MoreMost[44076:f803] Applications are expected to have a root view controller at the end of application launch
What is the problem?
Change this line:
[window addSubview:viewController.view];
to this:
window.rootViewController = viewController;
And you'll need to create the window, like this:
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
You don't need/want to add the view controller's view as a subview. You want to make your controller the root view controller and iOS will take care of the rest:
window.rootViewController = viewController;
That is, as of iOS 4. (Not sure the answer if you're going back earlier than that.)
You also need to create the window before you use it. Something like
window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
Not sure if you aren't or if you just didn't show it ...

iOS dev - UINavigationController: send data backwards to 2nd parent view

so, I need to send data backwards when poping two views. I tried using protocol, so this is part of my code:
RootViewController.h
#import <UIKit/UIKit.h>
#import "ThirdViewController.h"
#class SecondViewController;
#interface RootViewController : UIViewController <PassInt>
#property (strong, nonatomic) SecondViewController *secondViewController;
#property (strong, nonatomic) ThirdViewController *thirdViewController;
#property (nonatomic) int intNumber;
#end
RootViewController.m
#import "RootViewController.h"
#import "SecondViewController.h"
#implementation RootViewController
#synthesize secondViewController = _secondViewController;
#synthesize thirdViewController = _thirdViewController;
#synthesize intNumber = _intNumber;
- (void)setIntNumber:(int)number{
_intNumber = number;
}
#pragma mark - View lifecycle
- (void)viewWillAppear:(BOOL)animated {
if(!_thirdViewController){
_thirdViewController = [[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:[NSBundle mainBundle]];
}
if(!_secondViewController){
_secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:[NSBundle mainBundle]];
self.secondViewController.thirdViewController = self.thirdViewController;
}
[self.navigationController pushViewController:self.secondViewController animated:YES];
}
#end
SecondViewController.h
#import <UIKit/UIKit.h>
#class ThirdViewController;
#interface SecondViewController : UIViewController
#property (strong, nonatomic) ThirdViewController *thirdViewController;
#end
SecondViewController.m
#import "SecondViewController.h"
#import "ThirdViewController.h"
#implementation SecondViewController
#synthesize thirdViewController = _thirdViewController;
...
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
[self.navigationController pushViewController:self.userPreferencesViewController animated:YES];
}
#end
ThirdViewController.h
#import <UIKit/UIKit.h>
#protocol PassInt <NSObject>
#required
- (void) setIntNumber:(int)number;
#end
#interface ThirdViewController : UIViewController{
id <PassInt> delegate;
}
#property (retain) id delegate;
- (IBAction)saveChanges;
#end
ThirdViewController.m
#import "ThirdViewController.h"
#implementation ThirdViewController
- (IBAction)saveChanges{
int someInt = 3;
[[self delegate] setIntNumber:someInt];
UINavigationController *tempNavigationController = self.navigationController;
[tempNavigationController popViewControllerAnimated:NO];
[tempNavigationController popViewControllerAnimated:NO];
}
...
#end
I would appreciate any help!
In the UINavigationController reference check the property call :
#property(nonatomic, copy) NSArray *viewControllers
Discussion
The root view controller is at index 0 in the array, the back view controller is at index n-2, and the top controller is at index n-1, where n is the number of items in the array.
That could give you a handle to the rootViewController.
Would that be a good solution for you?
There is other ways. But from your comment I think that could be a match.
[[self.navigationController viewControllers] objectAtIndex:0].someProerty;
Another method could be to use NSNotifications. Have the RootViewController resgister as an observer for a notification posted by the ThirdViewController. Then in the userInfo dictionary of the notification posted by the ThirdViewController, you pass someInt as an NSNumber.
This provides sufficient abstraction because your ThirdViewController doesn't need to know what kind of object requires the information, it is just posting it so interested observers know about it.
Good Luck
You're never assigning anything to the delegate member of your ThirdViewController in the code you posted. Also, delegates should usually be assign, not retain.

Xcode 4 won't show app's main screen

After switching to Xcode 4, I thought I would be able to build and run my application exactly like I could in Xcode 3.
Turns out I can't.
Xcode 4 has a funny way of never showing the app's view controller, which is strange.
I can tell Apple's going to eventually force us to switch, which will result in my app being inoperable.
It gets to application:didFinishLaunchingWithOptions: without any errors, before hanging. Eventually the application crashes on the device - but stays on Default.png forever in the simulator.
I thought I could go and edit the application:didFinishLaunchingWithOptions: method the instantiate an instance of the view controller itself and add it to the window - only to reveal that didn't work either.
After numerous failed attempts at this - creating separate UIWindows for the main view controller - I decided the add it to a navigation controller.
Luck then struck me - but only in the simplest of forms. I looked in the log and see that applicationDidBecomeActive: had been called.
But, as usual, no such luck with any sort of view being displayed.
I then decided to see if I could add a UIView with a blue background color and a few UI elements (buttons, labels, etc...) to the window and see if that would work.
Funnily enough it did.
But why not for the main view controller? Not once in Xcode 4 have I successfully had it run my app (even opening it after it has been built fails). I've tried changing the compiler to the same as in Xcode 3, no luck.
I am honestly really confused as to why the application's view controller won't display.
For anyone who wants to give it an attempt as to why it isn't working that would be gratefully appreciated.
Here's the code for the AppDelegate, if you need the code for the view controller I can paste it here, however it's over 2000 lines.
Anyway, here's the .m file:
#import "DocumentationAppDelegate.h"
#import "DocumentationViewController.h"
#implementation DocumentationAppDelegate
#synthesize window;
#synthesize viewController;
#synthesize navigationController;
- (void)applicationWillEnterForeground:(UIApplication *)application {
NSLog(#"In method %#, which is in class %#.", NSStringFromSelector(_cmd), NSStringFromClass([self class]));
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSLog(#"In method %#, which is in class %#.", NSStringFromSelector(_cmd), NSStringFromClass([self class]));
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"In method %#, which is in class %#.", NSStringFromSelector(_cmd), NSStringFromClass([self class]));
DocumentationViewController *vc = [[DocumentationViewController alloc] init];
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController:vc];
controller.navigationBarHidden = YES;
UIWindow *win = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[win addSubview:controller.view];
[win makeKeyAndVisible];
return YES;
}
- (void)applicationWillTerminate:(UIApplication *)application {
}
- (void)dealloc {
[window release];
[super dealloc];
}
#end
and the .h
#import <UIKit/UIKit.h>
#class DocumentationViewController;
#interface DocumentationAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
DocumentationViewController *viewController;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet DocumentationViewController *viewController;
#end
If any one could help me here it would be tremendously appreciated.
Your app delegate already has the properties window, viewController and navigationController. So you can have the application:didFinishLaunchingWithOptions: method like this,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
viewController = [[DocumentationViewController alloc] init];
navigationController = [[UINavigationController alloc] initWithRootViewController:vc];
navigationController.navigationBarHidden = YES;
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}

Resources