I created a UIImagePickerController in the viewDidLoad method in my rootViewController.
- (void)viewDidLoad {
[super viewDidLoad];
UIImagePickerController *pickerController=[[UIImagePickerController alloc] init];
pickerController.sourceType=UIImagePickerControllerSourceTypeSavedPhotosAlbum;
pickerController.delegate=self;
[self presentModalViewController:pickerController animated:YES];
[pickerController release];
}
But the view of UIImagePickerViewController didn't appear on the screen.
The SDK version is 4.3
Is there some mistakes i make?
Thanks!
viewDidLoad is called after the view has been loaded and before the view is displayed. viewDidAppear: is called when the view is onscreen and is the correct point to present a modal view controller.
And if you want to do it only once, you might want to consider using a BOOL to keep track of it.
Related
I want to know what notification would I get in my CustomView class when this view will be displayed on screen.
CustomView *customView = [[CustomView alloc] init];
[self.view addSubview:customView];
NewViewController *newController = [[NewViewController alloc] init];
[self.navigationController pushViewController:newController animated:YES];
and after some work I pop this viewController.
[self.navigationController popViewControllerAnimated:YES];
I want to know what method in CustomView class will be called when that view will appear again on the screen.
Actually I have an infinite loop animation in that CustomView and on pushing to nextController I have to stop that animation loop and after coming back I need to start it again.
UIView doesn't get
viewWillAppear
viewDidDisappear
etc
ViewController in which it's contained, however, does, so, in order to pass it to UIView you are to implement following method:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[self.view.subviews objectAtIndex:0] viewWIllAppear]; // i assume your subview is the only one, otherwise you need to know the index, or have it as an ivar/property
}
Another idea - since you use your view a lot, i assume you do not recreate it. Let it be a property of your [[UIApplication sharedApplication] delegate]. Now you can access it like this:
#define SharedView [(appDelegate*)[[UIApplication sharedApplication] delegate] sharedView];
Then make custom UIViewController and overwrite viewWillAppear:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if ( [SharedView.superview isEqual:self.view] )
{
[SharedView viewWillAppear];
}
}
You answered it yourself.
viewWillAppear
Have you looked at: UIView
Observing View-Related Changes
– didAddSubview:
– willRemoveSubview:
– willMoveToSuperview:
– didMoveToSuperview
– willMoveToWindow:
– didMoveToWindow
I created a project using the View-Based Application template.
In my mainViewController:
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
UIImagePickerController *pickerController=[[UIImagePickerController alloc] init];
pickerController.sourceType=UIImagePickerControllerSourceTypeSavedPhotosAlbum;
pickerController.delegate=self;
[self presentModalViewController:pickerController animated:YES];
[pickerController release];
}
I implemented the delegate already.
But when I was running this project, I didn't get the imagePicker View. Instead of the imagePicker View, the view of mainViewController was shown on screen.
Did I make some mistakes?
Thanks!!!
You have put code in a wrong place viewDidUnload is called when a view unloads from memory. put your code into viewDidAppear:(BOOL)animated method.
I have a UINavigationController that contains 3 UIViewControllers on the stack.
View A - is the root
View B - is pushed by View A and has `self.navigationItem.hidesBackButton = YES;`
View C - is pushed by View B and has `self.navigationItem.hidesBackButton = NO;`
View C does not show the back button, even though I have hidesBackButton set to NO. How can I resolve this?
Update
A possible bug in 4.2 as it works till 4.1 sdks
I have tried this and mine is working perfectly. I am just posting the implementation of B view controller (BVC) and C view controller (CVC). My initial guess is that you are not setting the title of BVC in viewDidLoad.
#implementation BVC
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = #"I am B";
}
- (void) viewWillAppear:(BOOL)animated{
self.navigationItem.hidesBackButton = YES;
}
- (IBAction)pushB:(UIButton *)sender{
CVC *cvc = [[CVC alloc] initWithNibName:#"CVC" bundle:nil];
[self.navigationController pushViewController:cvc animated:YES];
[cvc release];
}
#end
#implementation CVC
- (void) viewWillAppear:(BOOL)animated{
self.navigationItem.hidesBackButton = NO;
}
#end
I think you have to set that property before you push or pop a view controller to affect the next view controller, setting it for the current viewcontroller in viewWillAppear is too late.
Edit: this looks like a bug in 4.2! The back button remains hidden both in the 4.2 simulator and on the device with 4.2, but it works in the 3.2, 4.1, and 4.0 simulators!
Here's the code where when pushing a VC with a hidden back button:
- (IBAction) goto2nd
{
SecondVC *vc = [[[SecondVC alloc] initWithNibName:#"SecondVC" bundle:nil] autorelease];
vc.navigationItem.hidesBackButton = YES;
[self.navigationController pushViewController:vc animated:YES];
}
That is all that should be needed, each VC has its own navigationItem, it's not a global setting, so you don't need to bother undoing it to restore the back button (at least when popping back to a VC where it is set to "NO").
Here's a workaround that I'm using successfully on 4.3.
Instead of hiding the back button, set the left bar button view to an empty view:
UIView *tmpView = [[UIView alloc] initWithFrame:CGRectZero];
UIBarButtonItem *tmpButtonItem = [[UIBarButtonItem alloc] initWithCustomView:tmpView];
[tmpView release];
self.navigationItem.leftBarButtonItem = tmpButtonItem;
[tmpButtonItem release];
To restore the back button, just set the left bar button item to nil:
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
Update: It appears as if the bug is gone in 4.3.
Note: Even though the bug seems to be fixed, I prefer the "empty view" technique because it allows the disappearance and reappearance of the back button to be animated.
The solution for this problem is somewhat tricky..just try it it will surely work since even I faced the same problem.
First set Navigation title in viewWillAppear.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationItem.title = #"SET YOUR TITLE";
}
When you are navigating to other page just set your navigation title to null.This will not show you any button on top.Since you can get rid of writing
self.navigationItem.hidesBackButton = YES; everytime.
- (IBAction)pushB:(UIButton *)sender
{
SecondVC *vc = [[[SecondVC alloc] initWithNibName:#"SecondVC" bundle:nil] autorelease];
self.navigationItem.title = #"";
[self.navigationController pushViewController:vc animated:YES];
[vc release];
}
I'm running the same issue and it's only happening on the iOS 4.2 simulator, so probably it's a bug on that version.
Reedit:
Try with this, it worked for me:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.navigationItem.hidesBackButton = NO;
}
Use the UINavigationControllerDelegate method -navigationController:willShowViewController:animated:. You will implement this in view controller A and view controller B. In A you will set -hidesBackButton: to YES and alternatively to NO in view controller B.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
viewController.hidesBackButton = YES;
}
You can also use following sample code;
- (void) viewWillAppear:(BOOL)animated{
self.navigationItem.hidesBackButton = YES;
}
- (void) viewWillDisappear:(BOOL)animated{
self.navigationItem.hidesBackButton = NO;
}
If your view heirarchy is really such that View B should not show a back button but View C should, then the simplest way to get around this is to refactor your heirarchy. I'm thinking of the following alternative:
View A calls presentModalViewController:animated: on View B*, a UINavigationController whose view property is View B. View B* pushes View C onto its navigation stack in response to an event (or otherwise) from View B. If you need to jump back to
View A quickly then call dismissModalViewControllerAnimated: on View A. If you want to keep the state of View B* and C in memory then you could also keep another pointer to View B* somewhere so it doesn't go away when dismissed.
I have an issue, viewWillAppear method in the UIViewController which is added to the screen by presentModalViewController method does not "go into" viewWillAppear method. Only time this method is invoked is together with the viewDidLoad, the first time.
- (IBAction)openModal:(id)sender {
if (self.nvc == nil) {
ModalViewController *vc = [[ModalViewController alloc] init];
self.nvc = vc;
[vc release];
}
self.nvc.segmentedIndex = [[self.navigationController.viewControllers objectAtIndex:0] index];
[self presentModalViewController:self.nvc animated:YES];
}
The property is of type retain.
Thanks in advance.
right, it works different and it now goes into viewWillAppear only once. So if you want to change the appearance of your view after dismissing a modal view you should do it using a modal delegate pattern. See the link:
http://useyourloaf.com/blog/2010/5/3/ipad-modal-view-controllers.html
Though it's for iPad, but you can get the idea. In the latest iOS versions it works the same.
Hope it helps
I'm having a problem making a universal app... In the application delegate I set up the main navigation for ipad and iphone:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
window = [[UIWindow alloc] initWithFrame:[ [UIScreen mainScreen] bounds]];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// The device is an iPad running iPhone 3.2 or later.
[self putSplitView];
} else {
[self putTabBar];
}
[window makeKeyAndVisible];
return YES;
}
- (void)putSplitView {
RootiPadViewController *rootiPadViewController = [[RootiPadViewController alloc] init];
UISplitViewController *splitController = [[UISplitViewController alloc] init];
splitController.viewControllers = [NSArray
arrayWithObjects:rootiPadViewController.seccionesView,
rootiPadViewController.noticiasView,
nil];
[window addSubview:splitController.view];
}
- (void)putTabBar {
TabBarController *tabBar = [[TabBarController alloc] init];
[window addSubview:tabBar.view];
}
RootiPadViewController is in charge of loading data an generating the panes for the splitView, so that its initialization incorporates a modalView with a loader, such that:
#implementation RootiPadViewController
#synthesize seccionesView, noticiasView;
- (id)init {
if ((self = [super init])) {
SeccionesVC_iPad *sec = [[SeccionesVC_iPad alloc] init];
NoticiasVC_iPad *not = [[NoticiasVC_iPad alloc] init];
self.noticiasView = not;
self.seccionesView = sec;
Init *initVC = [[Init alloc] init];
[self presentModalViewController:initVC animated:YES];
}
return self;
}
The code compiles without warnings, but for some reason the loadView method of initVC is never called and the modal view doesn't appear...
Any ideas why this might be happening?
thanks for your help!
Antonio
I know this is last year's question, but while I think I found the cause, I'm still trying to figure out a good non-hack solution for dealing with this.
Assuming you're working for iPad:
Upon initialization, splitViewController Master's viewDidLoad is called first, then the Detail's viewDidLoad.
If you attempt to put a modal window initializer in the Master's viewDidLoad, nothing seems to happen: This is because the Detail's viewDidLoad has executed after your modal view's viewDidLoad, resulting in your modal view being hidden away.
Breakpointing the modal view class, I see it enter initWithNibName in the modal view. I don't use ARC and here I assume your modal view doesn't dealloc until the program quits - The modal view is still there, but there's no way to get to it.
In iPhone:
Disregard this - because there is NO splitViewController for the iPhone. In fact, the default Universal splitViewController project treats the Master and Detail view as separate pages. So at application init, all you have to worry about is the Master viewDidLoad.
This is why, in a Universal project, pushing a modal view in viewDidLoad works as intended in the iPhone emulator, but NEVER in the iPad emulator.
Note that this only applies during the viewDidLoad stage; if you push a modal view AFTER viewDidLoad into the Master window, the modal view works as intended.
Maybe you should present your modal ViewController from the RootViewController 'ViewDidLoad' method, instead of the 'init' method... Not sure the view hierarchy is created that soon