I can't seem to launch the camera when loading my view. I end up making the user have to find and press a button on the screen just to load the camera (redundant). How can I do this? Code follows:
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.allowsImageEditing = NO;
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[super viewDidLoad];
[self presentModalViewController:self.imgPicker animated:YES];
}
UPDATE:
placing the above code into -viewDidAppear:(BOOL)animated allowed the camera to be launched, but the app crashed immediately afterward with the last routine being [UIWindowController transitionViewDidComplete:fromView:toView]; (as cited by Debugger)
You should do it in viewWillAppear:, or viewDidAppear: if the first doesn't work. trying to do it in viewDidLoad won't work because that is called after the view is first created, and the view isn't a subview of anything else at that point. As far as i understand it, in order to call presentModalViewController on self, the view must at some level be displayed in the UIWindow.
One other thing i just noticed; your code leaks memory depending on how you declare your imgPicker property. if it is declared with retain instead of assign, then unless you explicitly release it twice somewhere that picker will always exist in memory. You should autorelease the init'd object as you assign it to the property in that case.
Seems that it does not do it when you put the call to present modal view in view did load . You can try having a 2 second timer after the call to [super viewDidload] that pushes the picker view in or something like that.
Related
I have built a program without a menu. The main view has custom buttons which loads XIBs depending on which button is pressed. The only issue i'm having is when I go back to an already used view, its reset. I have tried "retain" in viewDidUnload and in viewWillUnload. I have tried everything I can thin of and cant get it to work.
- (IBAction)gotoMusicView:(id)sender{
//[self.view addSubview:musicview];
if(self.musicMenuData == nil)
{
musicMenu *musicview = [[musicMenu alloc]initWithNibName:#"musicMenu" bundle:[NSBundle mainBundle]];
self.musicMenuData = musicview;
musicview.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:musicview animated:YES];
[musicview release];
}
musicMenu *musicview = [[musicMenu alloc] initWithNibName:nil bundle:nil];
musicview.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:musicview animated:YES];
}
That musicview loads fine. After I leave that view and go back to the main view, it is RELEASED. Therefore when I reopen "musicview" everything , such as my UIWebView, has reset as if I am opening it again for the 1st time
Create a singleton class using this
And then initialize your .xibs there so you can use the same instance everytime you load the .xib. This way it'll never reset
Instead of allocating and initializing each time you need to use it, keep a reference of all the view controllers you're using, check of its nil on the first time if so initialize, example below.
if(self.someViewController == nil)
self.someViewController = [[ViewController alloc] initWithNibName:#"ViewController"....
//Now present self.someViewController..
Do this for the view controllers that you use for the tabs.
info: xcode 4.3.2, iOS5, using storyboard.
Created project from xcode's "Tabbed Application" template.
Did:
#implementation SUSecondViewController
UIImagePickerController *pic;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
pic = [[UIImagePickerController alloc] init];
pic.delegate = self;
// [pic setSourceType:UIImagePickerControllerSourceTypeCamera];
[self presentModalViewController:pic animated:YES];
}
When I click the tab the first time, the camera app is displayed.
When I click the tab the second time, the default view from the template is displayed, however I want the camera to be displayed every time the tab is clicked.
How can I make the camera appear every time I click a specific tab (with f.ex. a camera icon) ?
viewDidLoad only happens when the view is loaded.
If a view disappears / reappears it's not guaranteed that the view will get unloaded / loaded.
Maybe because there still is a strong pointer to the viewController somewhere, and the system doesn't need to free up some memory.
If you want to get it called every time the view appears, place that code in UIViewControllers
- (void)viewDidAppear
method instead of
- (void)viewDidLoad
You might also want to take a look here:
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html#//apple_ref/doc/uid/TP40007457-CH10-SW1
Use it on viewDidAppear: as on viewDidLoad you may not get some UI related things working as Nib is not completely loaded until viewDidLoad has finished executing.
So I would like you to code this on viewDidAppear: as shown below
#implementation SUSecondViewController
UIImagePickerController *pic;
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Do any additional setup after loading the view, typically from a nib.
pic = [[UIImagePickerController alloc] init];
pic.delegate = self;
// [pic setSourceType:UIImagePickerControllerSourceTypeCamera];
[self presentModalViewController:pic animated:YES];
}
Hope this helps you.
I have an iPhone view controller that's initialized with a XIB.
If a view controller's view is not visible when a memory warning comes through, it sets its view to nil (releasing it). But when an overlapping view is dismissed and the cleared-out view becomes visible again, Cocoa doesn't reload it from the XIB; it simply creates a blank one. This leaves a blank white screen, and a broken app.
The Apple doc for UIViewController's loadView method says, "If the view controller has an associated nib file, this method loads the view from the nib file. A view controller has an associated nib file if the nibName property returns a non-nil value." So I overrode loadView simply to check nibName after initializing the controller, and nibName is correct. So subsequent calls to loadView should be reloading from the XIB. I verified that loadView is called again after the memory warning.
UPDATE: With more testing and logging, I've determined that after the second viewDidLoad call, the view's IBOutlets are non-nil. Since I set them to nil in viewDidUnload, I conclude that the view was indeed reloaded from the XIB. So why is it showing up as an all-white screen?
Thanks for any insight.
Here's viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
_photoViewController = [[EGOSimplePhotoViewController alloc] initWithPhotoSource:_photoSource
scrollView:bigImageScrollView
enclosingView:photoSquare];
_photoViewController.delegate = self;
if(_progressHUD == nil)
{
if(self.navigationController.view != nil)
{
_progressHUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
}
else
{
_progressHUD = [[MBProgressHUD alloc] initWithView:self.view];
}
}
// Add HUD to screen.
if(self.navigationController.view != nil)
{
[self.navigationController.view addSubview:_progressHUD];
}
else
{
[self.view addSubview:_progressHUD];
}
[_progressHUD release];
_progressHUD.labelText = #"Loading...";
[_progressHUD show:YES];
}
And viewDidUnload:
- (void)viewDidUnload
{
[_photoViewController release];
[super viewDidUnload];
}
The viewControllers view loading mechanism after a memory warning is supposed to be transparent to the developer. you shouldn't have to do a thing to re-create the view.
For VCs loaded using nib, the system will re-create the view and viewDidLoad will be called.
For VCs loaded programatically loadView will be called again.
and the whole cycle repeats until viewDidAppear: and you see the view again.
USE CASE:
UITabBarController (2 tabs assumed)
User on Tab 0 >> Goes to Tab 1 >> Triggers memory warning >> All active VCs on UITabbarController receive memory warning >> UITabBarController will unload view of Tab0 >> Tab0 receives viewDidUnload:
When user switches back to Tab 0 its view will be created from scratch beginning from loadView OR viewDidLoad as I said.
If you are not receiving these events then your viewController hierarchy is messed up. Maybe you just added some VCs view as subView to something OR maybe your VC is not connected to window either directly OR through some container controller (UINavigation, UITabBarController etc) OR maybe you tried rolling up you own containerController and messed up.
Try understand the UIViewController lifecycle from loadView to viewDidUnload and dealloc. Its awesome. It will help a lot in writing good code and design of your apps.
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.
I'm trying to change the hidden property of a button and this is done in a method (View one):
-(void)changeSong:(NSString *)songName {
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:[[NSBundle mainBundle] pathForResource:songName ofType:#"mp3"]];
musicPlaying = YES;
playButton.hidden = YES;
pauseButton.hidden = NO;
}
This method is called from another view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MainMenuController *mainMenu = [[MainMenuController alloc] initWithNibName:#"MainMenu" bundle:nil];
[mainMenu changeSong:[songs objectAtIndex:indexPath.row]];
mainMenu = nil;
[mainMenu release];
[[self navigationController] popViewControllerAnimated:YES];
}
I know that the changeSong method is being called correctly because the music changes. However, the hidden property of the items don't change. I've tried calling [self.view setNeedsDisplay]; but this doesn't do anything.
Thanks
It looks like the MainMenuController hasn't finished initializing by the time you call -changeSong, which is why everything in MainMenuController is nil.
To solve this, either delay your call to -changeSong by using
[mainMenu performSelector:#selector(changeSong:) withObject:[songs objectAtIndex:indexPath.row] afterDelay:0.01];
or make your tableview the MainMenuController's delegate, and when MainMenuController is finished loading from the nib (using - (void)awakeFromNib in MainMenuController), call the delegate's method to change the song.
Since you're delaying the call in both cases, you'll have to be careful not to release the view controller before you do, so you'll have to change that code a little.
When initializing a view controller from a nib using -initWithNibName:bundle:, the actual view and its subviews aren't unarchived until the first time the view controller's view property is accessed, per the documentation:
The nib file you specify is not loaded right away. It is loaded the first time the view controller’s view is accessed. If you want to perform additional initialization after the nib file is loaded, override the viewDidLoad method and perform your tasks there.
Try calling [mainMenu view] right after you initialize it from the nib. That will hydrate the view hierarchy from the nib.
However, I guess I don't understand why you're unarchiving a view controller from a nib and calling one of its methods that affects the UI (i.e., hiding or revealing buttons) without pushing that view controller to a navigation controller or presenting it modally. -changeSong: is a method on MainMenuController, so simply calling it right after you initialize MainMenuController won't have any effect on the buttons that it manages.
(Unrelated: You're setting mainMenu to nil before releasing it, which effectively means mainMenu can never be released. Call -release first, then, optionally, set it to nil.)