Error with presenting UIImagePickerController modally - iphone

I have a strange problem presenting the UIImagePickerController modally in my iOS 6 app. The XCode gives me this error:
Warning: Attempt to present <UIImagePickerController: 0x1e025040> on <UINavigationController: 0x1d51ce00> whose view is not in the window hierarchy!
I have the following window hierarchy in my AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window = window;
firstViewController = [[SGNewMailViewController alloc] init];
navController = [[UINavigationController alloc] initWithRootViewController:firstViewController];
self.window.rootViewController = firstViewController;
[self.window makeKeyAndVisible];
return YES;
}
In my SGNewMailViewController I present a new UIView, a member of SGFoldingAttachmentView class which has this code in it:
- (void)choosePhotoPressed {
SGNewMailViewController *mailVC = [((SGAppDelegate *)[UIApplication sharedApplication].delegate).firstViewController.navigationController.viewControllers lastObject];
[mailVC displayCameraRoll];
}
In the end, here's my SGNewMailViewController displayCameraRoll method:
- (void)displayCameraRoll {
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeSavedPhotosAlbum])
{
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
[self presentViewController:imagePicker animated:YES completion:nil];
}
}
So what can possibly be the problem? Is it in the custom view presented from another class? How should I fix it? Thanks in advance!

Make the UINavigationController to be the root view controller of your window. This should fix the problem
self.window.rootViewController = navController;

Related

How to link nested viewcontrollers using the child viewcontroller pattern

Compiling and running using iOS 7 - getting warning message: "Presenting view controllers on detached view controllers is discouraged" while presenting modal view controller. I have learned that viewcontrollers with linked using the child viewcontroller pattern will not produce warning. Can someone suggest way to link nested viewcontrollers using the child viewcontroller pattern to avoid warning message.
(void)applicationDidFinishLaunching:(UIApplication *)application
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
self.loginRootviewController = [[MainViewController alloc] initWithNibName:#"MainViewController-iPad" bundle:nil];
}
else
{
self.loginRootviewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
}
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.loginRootviewController];
DDMenuController *rootController = [[DDMenuController alloc] initWithRootViewController:navController];
_menuController = rootController;
AppMainMenuViewController *leftController = [[AppMainMenuViewController alloc] init];
rootController.leftViewController = leftController;
self.loginRootviewController.delegateLogin = leftController;
self.window.rootViewController = rootController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
}
instead of using DDMenuViewController use SWRevealViewController. It is updated for iOS 7 and has more functionality than DD

how to change the rootviewcontroller

I want to change the rootViewController after the authenticationViewController
-(IBAction)LoginButtonPushed:(id)sender {
if ([(VerifyId)isEqual:#"C"]){
CondidatsViewController *condidatsViewController = [[[CondidatsViewController alloc]initWithNibName:#"CondidatsViewController" bundle:nil]autorelease];
UINavigationController *navController = self.navigationController;
NSMutableArray *controllers = [[self.navigationController.viewControllers mutableCopy] autorelease];
[controllers removeLastObject];
navController.viewControllers = controllers;
[navController pushViewController:condidatsViewController animated: YES];
} else {
RecruteursViewController *recruteursViewController = [[[RecruteursViewController alloc]initWithNibName:#"RecruteursViewController" bundle:nil]autorelease];
UINavigationController *navController = self.navigationController;
NSMutableArray *controllers = [[self.navigationController.viewControllers mutableCopy] autorelease];
[controllers removeLastObject];
navController.viewControllers = controllers;
[navController pushViewController:recruteursViewController animated: YES];
}
}
this code is when i press in login button i want CondidatsViewController or RecruteursViewController will be the rootView
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
AcceuilViewController *viewController =[[[AcceuilViewController alloc]
initWithNibName:#"AcceuilViewController" bundle:nil]autorelease];
self.navController = [[[UINavigationController alloc]initWithRootViewController:viewController]
autorelease];
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
return YES;
}
You can try UINavigationController's following method with a new array of desired view controllers something like
[self.navigationController setViewControllers:#[newRootViewControllerInstance, secondVCInstanceIfRequired, thirdVC-and-so-on....] animated:NO];
It will do the trick ;)
How about have a view controller one level above your nav and auth view controllers? This view controller can check for a valid session and push whatever view is appropriate on top of the stack. It seems ill advised to try to change your root view controller.
Edit: More details
You have a root view controller that doesn't have a view tied to it like most other view controllers might. You set this class as the root view controller in your app delegate.
App Delegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
RootViewController *rootViewController = [[RootViewController alloc] init];
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
In your root view controller you can determine if you have a valid session or not. Based on that, you can render the appropriate view.
RootViewController.m
#interface RootViewController ()
#end
#implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
BOOL isUserAuthenticated = [MyClasskToFigureOutIfUserIsAuthenticated isUserAuthenticated];
if(isUserAuthenticated == NO) {
AuthViewController *vcAuth = [[AuthViewController alloc] init];
[self addChildViewController:vcAuth];
[self.view addSubView:vcAuth.view];
} else {
//they are authenticated so push your other view controller.
}
}
#end
This is pretty rough, but it should point you in the right direction.

how to load different xibs in iphone and ipad?

I wanna at certain point of the program to load different xib for iphone and for ipad but wanna to reuse most part of the code. how can I achieve this ?
Append ~ipad or ~iphone to the end of the file name. So SomeViewController~ipad.xib or SomeViewController~iphone.xib for instance.
See iOS Supports Device-Specific Resources.
If you create a template project that is universal you can inspect the code created for that version. For Example:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController_iPhone" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
self.window.rootViewController = self.navigationController;
} else { // iPad
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController_iPad" bundle:nil];
UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
PSGameViewController *detailViewController = [[PSGameViewController alloc] initWithNibName:#"DetailViewController_iPad" bundle:nil];
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
self.splitViewController = [[UISplitViewController alloc] init];
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController, detailNavigationController, nil];
self.window.rootViewController = self.splitViewController;
}
[self.window makeKeyAndVisible];
return YES;
}
or from tableView:didSelectRowAtIndexPath:
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if (self.detailViewController == nil) {
self.detailViewController = [[PSGameViewController alloc] initWithNibName:#"PSGameViewController_iPhone" bundle:nil];
}
self.detailViewController.model = selectedModel;
[self.navigationController pushViewController:self.detailViewController animated:YES];
self.pushedIndexPath = indexPath;
} else { // iPad
self.detailViewController.model = selectedModel;
}

Correct way to show Login Screen followed by UITabbarController menu

I need to implement the following and I wanted to know the correct way to do it.
when the iPhone application launches, I need to show a logo image for 2 seconds followed by showing a login screen that allows the person to login or create an account. Once the person logs in, i need to show a tabbarcontroller menu options.
This is how I'm currently doing it:
In the AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
LoginViewController *viewController0 = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
UINavigationController *aNavigationController0 = [[UINavigationController alloc] initWithRootViewController:viewController0];
self.window.rootViewController = aNavigationController0;
// I also implement an iVar of the UITabBarController here...
// ....
}
The #implementation:
#implementation LoginViewController
- (IBAction)createNewAccountButtonClicked:(id)sender {
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
delegate.window.rootViewController = delegate.tabBarController;
}
So, my questions are:
Is this the correct way to show the tabbar for my purpose?
In this scheme of things, I cannot show the logo animated. Any pointers on how to do this?
The code below assumes you're using ARC, if you're not then you'll need to do your MRC.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.tabBarController = [[UITabBarController alloc] initWithNibName:nil bundle:nil];
self.window.rootViewController = self.tabBarController;
LoginViewController *loginViewController= [[LoginViewController alloc] initWithNibName:nil bundle:nil];
loginViewController.delegate = self;
UINavigationController *loginNavCont = [[UINavigationController alloc] initWithRootViewController:loginViewController];
[self.tabBarController presentModalViewController:loginNavCont animated:NO];
UIImageView *splashScreen = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default"]];
[self.window addSubview:splashScreen];
[UIView animateWithDuration:0.5
delay:2.0
options:0
animations:^{
splashScreen.alpha = 0.0;
}
completion:^(BOOL finished) {
[splashScreen removeFromSuperview];
}];
[self.window makeKeyAndVisible];
return YES;
}
- (void)loginViewControllerShouldBeDismissed:(UIViewController *)viewController
{
[self.tabBarController dismissModalViewControllerAnimated:YES];
}

how to push UIImagePickerController into UINavigationController?

I have following coding in my Program, in AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
myList = [[List alloc] init];
mySettings = [[Settings alloc] init];
myCriteria = [[Criteria alloc] initWithStyle:UITableViewStyleGrouped];
first = [[UINavigationController alloc] initWithRootViewController:myList];
second = [[UINavigationController alloc] initWithRootViewController:mySettings];
third = [[UINavigationController alloc] initWithRootViewController:myCriteria];
myTabBar = [[UITabBarController alloc] init];
myTabBar.view.frame = CGRectMake(0,20,320,460);
UITabBarItem *first1 = [[UITabBarItem alloc] initWithTitle:#"List" image:[UIImage imageNamed:#"list.png"] tag:0];
UITabBarItem *second2 = [[UITabBarItem alloc] initWithTitle:#"My Profile" image:[UIImage imageNamed:#"settings.png"] tag:1];
UITabBarItem *third3 = [[UITabBarItem alloc] initWithTitle:#"Criteria" image:[UIImage imageNamed:#"Criteria.png"] tag:2];
UINavigationController *localNavigationController = [[UINavigationController alloc] initWithRootViewController:myTabBar];
first.tabBarItem = first1;
second.tabBarItem = second2;
third.tabBarItem = third3;
myControllerArray = [[NSArray alloc] initWithObjects:first, second, third, nil];
[myTabBar setViewControllers:myControllerArray];
[myTabBar setCustomizableViewControllers:myControllerArray];
[self.window addSubview:myTabBar.view];
// Add the view controller's view to the window and display.
// [self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
Where these three are different classes, now I want to use camera and album, so when I write coding as below on a button target, it won't work
- (void) useCamera
{
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera])
{
NSLog(#"If is true");
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
// [self.navigationController pushViewController:imagePicker animated:YES];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
[self.tabBarController setCustomizableViewControllers:[[NSArray alloc]initWithObjects:imagePicker,self,nil]];
[self.tabBarController setViewControllers:[[NSArray alloc]initWithObjects:imagePicker,self,nil]];
//[self presentModalViewController:imagePicker animated:YES]; I tried
//[self.view addSubview:imagePicker.view]; I tried
//self.view=imagePicker.view; I tried
//[myScrollView addSubview:imagePicker]; I tried
//[myView addSubview:imagePicker]; I tried
[imagePicker release];
newMedia = YES;
}
}
I tried all the above ways but they are not working and showing UIImagePickerController,
now what should I do
if anyone in not clear from my question, can ask me again.....
What about [self.view addSubview:imagePicker.cameraOverlayView]
Also, have you tried adding any other view to your self.view? I wonder if the imagePicker is being added, but is not loaded because the view you are adding it to is not being displayed.
Did u try presenting the imagePicker through one of the navigation controllers?
From Reference
Present the user interface by calling the presentModalViewController:animated: method of the currently active view controller, passing your configured image picker controller as the new view controller. On iPad, you can alternatively present the user interface using a popover as described in initWithContentViewController: and “Presenting and Dismissing the Popover” in UIPopoverController Class Reference.
If using GKImagePicker:
[self.view addSubview:self.imagePicker.imagePickerController.view];
You can always do:
let cam = UIImagePickerController()
cam.delegate = self
cam.sourceType = .camera
self.show(cam, sender: nil)
worked for me
Did you try presenting the UIImagePickerController through the tabBarController (UITabBarController inherits from UIViewController)? Assuming that you created a singleton for for your AppDelegate and that the tabBarController is a property of the AppController (for your convenience I added a sample code for the singleton below), the code would look something like this:
AppController.h
#import <UIKit/UIKit.h>
#interface AppController : NSObject <UIApplicationDelegate> {
UITabBarController *tabBarController;
}
// Class methods for convenience
+ (AppController *)sharedAppController;
// *** Properties
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) UITabBarController *tabBarController;
#end
AppController.m
#import "AppController.h"
static AppController *sharedInstance;
#implementation AppController
#synthesize window=_window;
#synthesize tabBarController;
#pragma mark - Initialization
- (id)init
{
// Create the sharedInstance of the application
if (sharedInstance) {
NSLog(#"Error: You are creating a second AppController");
}
[super init];
sharedInstance = self;
return self;
}
+ (AppController *)sharedAppController
{
return sharedInstance;
}
- (void)dealloc
{
[_window release];
[tabBarController release];
[super dealloc];
}
Now in your class, on the useCamera method call the imagePicker by doing this:
- (void)useCamera
{
// YOUR CODE ...
// Place image picker
[[[AppController sharedAppController] tabBarController]
presentModalViewController:imagePicker animated:YES];
// YOUR RELEASE CODE ...
}
Good luck and happy coding!