Question about presentModalViewController - iphone

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.

Related

How to release ViewController after pushviewcontroller

I have 2 view, named viewcontroller1,viewcontroller2. every viewcontroller has load about 3 pictures(load it in XIB) , when i try to use [self.navigationcontroller pushviewcontroller], to push view1 to view2, the memory cannt release.(i want to konw it cannt release viewcontrller1 or cannt release uiimageview)any error for my code ??
viewcontroller1 code just like this:
viewcontroller1.h
#interface ViewController : UIViewController
#property(strong,nonatomic)IBOutlet UIImageView *mainImageView;
#property(strong,nonatomic)IBOutlet UIImageView *topwallImageView;
#property(strong,nonatomic)IBOutlet UIImageView *buttonImageView;
viewcontroller1.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
self.mainImageView = nil;
self.topwallImageView = nil;
self.buttonImageView = nil;
[super viewDidUnload];
// Release any retained subviews of the main view.
}
-(void)dealloc
{
[mainImageView release];
[topwallImageView release];
[buttonImageView release];
[super dealloc];
}
-(IBAction)main2ViewController:(id)sender
{
Main2ViewController *main2ViewController =[[Main2ViewController alloc]initWithNibName:#"Main2ViewController" bundle:nil];
[self.navigationController pushViewController:main2ViewController animated:NO];
[main2ViewController release];
}
You have to study more detailed about Object Communication and Memory management in iOS.
Also please try to use ARC. Automatic reference counting (ARC) was introduced in the iOS 5 sdk to free Objective-C programmers from having to handle memory management by making memory management the job of the compiler.
You can convert your project to ARC enabled using this link
You can't release viewcontroller1 and its IBOutlet properties while viewcontroller2 is visible or after pushed viewcontroller2. Because you pushed viewcontroller2 from viewcontroller1.viewcontroller1 is the container/parent of viewcontroller2. viewcontroller2 will not exist with out viewcontroller1
About the IBOutlet imageview images, you can set it to nil .Eg: yourImageview.image = nil; However it will not release the IBOoutlet Imageview memory.
IBOutlet imageview will get released when a release method called to viewcontroller1 because you released it properly in viewcontroller1 dealloc method :)
About your Main2ViewController method:You handled memory properly in your code
When you call the pushViewController , it will retain the controller which is pushed by default. note that your are not the owner. It will release automatically when the controller is popped out.However you have to release the allocated Main2ViewController. So your code is fine :)

ViewDidLoad method in UIViewController - when does it get called?

I have a UIViewController called LaunchController that is launched in my iPhone app when the app first opens:
#interface LaunchController : UIViewController<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
Then, when a button is clicked, I push another view controller:
MainController *c = [[MainController alloc] initWithImage:image];
[self presentModalViewController:c animated:NO];
MainController has the following constructor, which I use:
- (id)initWithImage:(UIImage *)img
{
self = [super init];
if (self) {
image = img;
NSLog(#"inited the image");
}
return self;
}
and then it has a viewDidLoad method as follows:
- (void)viewDidLoad
{
NSLog(#"calling view did load");
[super viewDidLoad];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:imageView];
NSLog(#"displaying main controller");
}
When the program runs, I see that the constructor for MainController is called (due to the output of NSLog), however viewDidLoad never gets called, even though I am calling presentModalViewController. Why is this? Why isn't viewDidLoad being called?
I think it is something as followings. When you need the property of view inside UIViewController, it will be loaded with lazy manner.
- (UIView *)view
{
if (_view == nil) {
[self loadView]; //< or, the view is loaded from xib, or something else.
[self viewDidLoad];
}
return _view;
}
After the view initialized, it will call viewDidLoad to inform the UIViewController.
You aren't loading your view controller from a xib file, and from comments you don't have anything in loadView (which is where you would create your view controller's view if you were not using a xib file).
Therefore, your view isn't being loaded, so viewDidLoad is never called.
Typically you would use initWithNibName: to initialise a new view controller, and then set the image after it (so expose the image as a property).
viewDidLoad will be called as soon as your controller's view property is accessed, that is when you display it for the first time or request it (e.g. have some code that calls c.view.
The reason viewDidLoad is not being called is because you aren't loading a view.
In your init method:
self = [super init];
means that you are just creating a naked view from scratch. not loading one from a nib.
try this instead:
self = [super initWithNibName:nil bundle:nil];
If you have a xib or nib file with the same name as the view controller class it should find if. Otherwise, you can just give a nibName that works.
UPDATE:
If you are not using nib files, then the appropriate method is NOT viewDidLoad. You have to implement loadView instead of viewDidLoad.
In your specific case, just put everything that is currently in viewDidLoad into loadView.

popviewcontroller is not calling viewWillappear

I'm using the following code to display the previous view when a user is clicking on a button
[self.navigationController popViewControllerAnimated:YES];
In the previous view, I overwrite viewWillAppear to initialized few things. However, it seems like viewWillAppear is not being called. I put NSLog in viewDidload, viewWillAppear, viewDidAppear and only viewDidAppear is being called. Is this normal behavior? If yes, what event should I override so I can do my initialization? Thank you.
As requested -viewWillAppear for the previous view
- (void)viewWillAppear:(BOOL)animated{
NSLog(#"ViewWillAppear");
//[[GameStore defaultStore] resetGame];
[self setHangmanImage];
NSLog([[[GameStore defaultStore] selectedList] label]);
[labelListName setText:[NSString stringWithFormat:#"List Name: %#", [[[GameStore defaultStore] selectedList] label]]];
[labelCurrentIndex setHidden:YES];
[labelCurrentWord setHidden:YES];
[[self navigationController] setNavigationBarHidden:NO];
[FlurryAnalytics logEvent:#"GameViewController - viewWillAppear"];
[self getNewQuestion];
NSLog(#"ViewWillAppear finish");
[super viewWillAppear:YES];
}
I setup the UINavigationalController in the app delegate using the following code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
HomeViewController *hv = [[HomeViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:hv];
// You can now release the itemsViewController here,
// UINavigationController will retain it
[hv release];
// Place navigation controller's view in the window hierarchy
[[self window] setRootViewController:navController];
[navController release];
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
return YES;
}
UPDATE
I don't know what happened but last night after trying to run the app one more time in the simulator and its still having this issue, I decided to save everything and shut my computer down since it was getting late.
This morning I turned my computer back on opened up xcode, clean the project and build and run it and I the problem is fixed and -viewWillAppear is called. I didn't change anything and its working. I added NSLog in -willShowView and its not getting called. I don't know why all of a sudden viewWillAppear is being called.
Make sure your navigation controller's delegate is set and then use this function to call viewWillAppear in the class whose viewWillAppear you want to call:
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[self viewWillAppear:animated];
}
I've just hit a problem very much the same and after some testing discovered that calling popViewControllerAnimated: in a block (from a network response in AFNetworking) viewDidAppear isn't called in the parent view.
The solution that worked for me here was to call it in the main thread instead.
dispatch_async(dispatch_get_main_queue(), ^{
// If not called on the main thread then the UI doesn't invoke the parent view's viewDidAppear
[self.navigationController popViewControllerAnimated:YES];
});
I have just hit this problem as well the root cause of this problem is because I put self.navigationController.delegate = self on viewDidLoad. My solution is to put the delegation on viewWillAppear :
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.navigationController.delegate = self;
}
After that popViewController will hit viewWillAppear.

Why my presentModalViewController method doesn't work

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.

presenting a modal view over a splitView

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