I have an app that uses the UITabBarController and one of the tabs is supposed to be a full on camera view (similar to Instagram). When I launch the app and go to that view, most of the screen is blank and no image library picker/camera view loads. Any help would be greatly appreciated.
Here is my viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
imagePicker = [[UIImagePickerController alloc] init];
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
} else {
[imagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
}
[imagePicker setDelegate:self];
[imagePicker setEditing:NO];
// Place image picker (camera viewing angle on the screen)
[self presentViewController:imagePicker animated:YES completion:nil];
}
Try putting that code in viewDidAppear instead -- that worked for me. Better yet, would be to put all but the last line in viewDidLoad, so it's only called once, and just put the last line in the viewDidAppear method. When you cancel the image picker (the only thing I tested), it will just reappear, since viewDidAppear will be called again, so you need to implement imagePickerControllerDidCancel: like this to keep that from happening:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[self dismissViewControllerAnimated:YES completion:nil];
self.imagePicker = nil;
}
And, in your viewDidAppear, put in an if statement to see if the picker exists before trying to present it:
if (self.imagePicker) {
[self presentViewController:self.imagePicker animated:YES completion:nil];
}
Related
I have a storyboard that looks like this:
This is how it works: the InitialSlidingViewController instantiates the Navigation VC as the topViewController as follows in its .m file:
-(void)viewDidLoad {
[super viewDidLoad];
self.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Navigation"];
}
After the Navigation VC gets instantiated, it creates the underlying Menu and sets that as the underLeftVC. This is using ECSlidingViewController. This creates a sliding menu that uses a pan gesture, similar to Facebook.
The rootVC for the NavigationVC is my ItemsCDTVC. When I click the + button, it pops up an action sheet that allows me to take a photo from the camera or choose from the photo library. However, I then want it to modally segue to the ManageItemVC and set the picture I just chose/took to its UIImageView. When I try to present, it throws the following error:
Warning: Attempt to present <ManageItemViewController: 0x81d52a0> on <InitialSlidingViewController: 0x8122ce0> whose view is not in the window hierarchy!
Which is true, because InitialSlidingVC is not on screen, ItemCDTVC is, but how do I fix this?
I have set the modal type segue in my Storyboard with an identifier from the flexible space at the bottom (when tapped, it doesn't do anything, so I chose that to create a visual segue). This is my segue code in ItemCDTVC:
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// let's get the edited image
UIImage *image = info[UIImagePickerControllerEditedImage];
// but if for some reason we disable editing in the future, this is our safeguard
if(!image) image = info[UIImagePickerControllerOriginalImage];
if(image) {
self.pictureImageView.image = image;
[self performSegueWithIdentifier:#"addItemSegue" sender:self];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"addItemSegue"]){
ManageItemViewController *manageItemVC = (ManageItemViewController *)[segue destinationViewController];
manageItemVC.pictureImageView = self.pictureImageView;
}
}
It fails when trying to present the modal VC.
Fixed, the only thing I had to do is dismiss the imagePickerController before trying to perform the segue, as so:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// let's get the edited image
UIImage *image = info[UIImagePickerControllerEditedImage];
// but if for some reason we disable editing in the future, this is our safeguard
if(!image) image = info[UIImagePickerControllerOriginalImage];
if(image) {
self.pictureImage = image;
[self dismissViewControllerAnimated:NO completion:^{
[self performSegueWithIdentifier:#"addItemSegue" sender:self];
}];
}
}
Is it possible to pop up an UIViewController (xib file) like UIPopOverControl in iPad ?
I have a separate NIB file which is linked to an UIViewController. I want to popup that NIB file along with the button pressed with a customised size (200,200).
Is this possible?
I am trying to get something like this on the iPhone - http://www.freeimagehosting.net/c219p
You can also use one of these custom made clases to show a popup:
https://github.com/sonsongithub/PopupView
https://github.com/werner77/WEPopover
https://github.com/50pixels/FPPopover
Example with FPPopover:
//the view controller you want to present as popover
YourViewController *controller = [[YourViewController alloc] init];
//our popover
FPPopoverController *popover = [[FPPopoverController alloc] initWithViewController:controller];
//the popover will be presented from the okButton view
[popover presentPopoverFromView:okButton];
//release if you arent using ARC
[controller release];
yes it is. load Your pOpOver controller lazily at the point when it is needed. add its view as a subview (you could animate the addition). make its frame size what You need and add the image You have shown as a background subview of the pOpOver controller along with other controls You want in the pop up.
good luck
UPDATE:
alright, ii will show You how ii do this in my app Lucid Reality Check (deployment target iOS4.3).
one can use a UIPopoverController to present another controllers view. what ii do first is to make sure ii always know the current orientation of the device, so ii can reposition the popup on rotation (maybe this works by itself on iOS6?). so in my base controller (from where ii want to show a popup) ii have an instance variable like this:
UIInterfaceOrientation toOrientation;
and also:
UIPopoverController *popover;
UIButton *popover_from_button;
BOOL representPopover;
popover will be reused for all popups, and popover_from_button will hold the button from which the popup is initiated.
then the next code comes into the base controller:
- (void)popoverWillRotate {
if ([popover isPopoverVisible]) {
[self dismissPopover];
representPopover = YES;
}
}
- (void)popoverDidRotate {
if (popover && representPopover) {
representPopover = NO;
[self representPopover];
}
}
these two methods have to be called every time the device is rotated, like this:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
//DLOG(#"willRotateTo %i", toInterfaceOrientation);
toOrientation = toInterfaceOrientation;
if ([Kriya isPad ]) {
[self popoverWillRotate];
}
}
as one can see, first the orientation is captured then popoverWillRotate is called. this would hide the popover during the orientation animation. and after rotating, the popover must be redisplayed like this:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
//DLOG(#"didRotateFrom %i", fromInterfaceOrientation);
//[self layout:toOrientation]; //do some layout if You need
if ([Kriya isPad]) {
[self popoverDidRotate];
}
}
- (void)layout:(UIInterfaceOrientation)toInterfaceOrientation {
//one can do view layout here, and call other controllers to do their layout too
}
now that the orientation changes are worked out, the code for presenting the popover arrives here:
#pragma mark Popovers
- (void)presentPopoverWith:(id)controller fromButton:(UIButton*)button {
if (popover)
[popover release];
if (popover_from_button)
[popover_from_button release];
popover_from_button = [button retain];
popover = [[UIPopoverController alloc] initWithContentViewController:controller];
[popover setDelegate:self];
[self representPopover];
}
- (void)representPopover{
if (popover) {
UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirectionAny;
UIViewController *vc = (UIViewController*)[popover contentViewController];
CGSize contentSize = [vc contentSizeForViewInPopover];
if (contentSize.width > 0 && contentSize.height > 0) {
[popover setPopoverContentSize:contentSize animated:NO];
}
//DLOG(#"representPopover rect:%#", [Kriya printRect:popover_from_button.frame]);
[popover presentPopoverFromRect:CGRectOffset(popover_from_button.frame, 0, popover_from_button.frame.size.height + 7.0) inView:self.view permittedArrowDirections:arrowDirection animated:YES];
}
}
- (void)dismissPopover {
if (popover) {
[popover dismissPopoverAnimated:YES];
}
}
finally, if one wants to be notified when the popover is dismissed, the base controller must implement a delegate method:
#pragma mark UIPopoverControllerDelegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
//do something important here like drink some water
}
and don't forget to make the base controller a UIPopoverControllerDelegate in its header.
a use case for this way of doing popups would then look like this:
- (void)takeImage {
UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
[picker setDelegate:self];
[picker setAllowsEditing:NO];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[picker setSourceType:UIImagePickerControllerSourceTypeCamera];
if ([Kriya isPad]) {
[self presentPopoverWith:picker fromButton:backgroundImageButton];
} else {
//modals on iPhone/iPod
//DLOG(#"takeImage addSubview picker");
[self presentModalViewController:picker animated:YES];
}
} else {
//DLOG(#"no camera");
}
}
this would use an image picker as the content for the popup, but one can use any controller with a valid view. so just do this:
[self presentPopoverWith:popupsContentController fromButton:tappedButton];
one should not have any missing information, :), the method [Kriya isPad] is just this:
+ (BOOL)isPad {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
// iPad capable OS
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
//this is an iPad
return YES;
}else {
//this is an iPod/iPhone
return NO;
}
#else
//can not pissible be iPad
return NO;
#endif
}
ENJOY!
I have a button where when the user presses it, he is navigated to camera to take a pic.
When he takes the pic, he presses done and gets back to the controller. But when that happens the navigation bar gets up in the screen, gets below the battery/signal bar that the telephone has. The weird thing is that this happens on 4/4s but not on 3gs
It is rather tough to answer the question without knowing a bit more details, but here's some code I use to bring up the camera, take the picture, then close the camera successfully. The method can be called by using one line of code: [self takePhoto];
- (void) takePhoto {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
//Clear out the UI first
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
//picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; -> use this if you want them to select from the library
[self presentViewController:picker animated:YES completion:nil];
} else {
//Device does not support a camera, show a message if desired
}
}
Then you need a delegate for it all so the program knows what to do when an image is taken or selected and how to close, that's what this code is:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
self.workingImage = nil;
//I grab the image and store globally, but first I manually scale and rotate it if necessary
self.workingImage = [self scaleAndRotateImage:[info objectForKey:UIImagePickerControllerOriginalImage]];
//I display the image in my UI view, so this chunk of code will size it properly
CGRect bound;
bound.origin = CGPointZero;
bound.size = img.size;
imageView.bounds = bound;
//Set the UI image view and dismiss the controller
[imageView setImage:self.workingImage];
[picker dismissModalViewControllerAnimated:YES];
}
Obviously, make sure your controller .h implements the delegate properly like so:
#interface ViewController : UIViewController<UIImagePickerControllerDelegate> { ... }
Hope this helps?
I have this code that loads a new UIView (from storyboard) when a button is pressed. goPressed function is fired on button pressed and it calls selectImage function. selectImage opens a UIImagePickerController and lets user select a photo. After user has selected the photo, didFinishPickingMediaWithInfo delegate adds the selected image to a UIImageView.
In 'goPressed', after selectImage is performed, it should be performing a Segue at like commented as //1. But nothing happens. performSegueWithIdentifier doesn't seem to be working. And if I don't call [self selectImage] before calling performSegueWithIdentifier, it works. Here is the code:
- (IBAction)goPressed:(id)sender {
[self selectImage];
[self performSegueWithIdentifier:#"lastView" sender:currentSender]; //1
}
-(void)selectImage
{
// Create image picker controller
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
// Set source to the camera
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
// Delegate is self
imagePicker.delegate = (id)self;
// Allow editing of image ?
imagePicker.allowsEditing=NO;
// Show image picker
[self presentModalViewController:imagePicker animated:YES];
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Access the uncropped image from info dictionary
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
[[picker presentingViewController] dismissModalViewControllerAnimated:YES];
lePreview.image= image;
}
Please help, why performSegueWithIdentifier isn't working? I hope I am not missing any information you need.
I'm assuming that the view you are trying to segue to is using the picture you get just before you do your segue? If they cancel from the image picker do you still want to segue?
If it needs the picture, then maybe you should call your segue after the delegate call "did finish picking".
The issue with the segue not firing may be due to the animation still occurring from here:
[[picker presentingViewController] dismissModalViewControllerAnimated:YES];
You can try:
[[picker presentingViewController] dismissModalViewControllerAnimated:NO];
or if you want to maintain the animation, move the segue to the "picker did finish" method and do it this way:
[self dismissModalViewControllerAnimated:YES completion:^() {
[self performSegueWithIdentifier:#"lastView" sender:self];
}];
or if that does not work try this approach in the pickerdidfinish method (note - this should be implemented as a delegate in the controller that calls the modal view, not the modal view itself:
//maintain the animation
[self dismissModalViewControllerAnimated:YES];
//slight pause to let the modal page dismiss and then start the segue
double delayInSeconds = 0.5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//code to be executed on the main queue after delay
[self performSegueWithIdentifier:#"lastView" sender:self];
});
I use this transition frequently and it makes a nice drop away with the modal view then slides in the segue view and the pause allows the transition to seem natural.
I have a strange issue on ios 4.3.I have one of my screen in landscape mode, a button click presents a popover.My popover has a search bar.Whenever keyboard appears it automatically pushes my popover bit up.When I resign the keyboard , popover reduces in height.This is the issue only on ios 4.3.While in rest of the ios , my popover doesnot reduces in height after keyboard dismissal.
None of the answers above worked for me. Apparently the keyboard scales the view and restores this scaling after the UIKeyboardDidHideNotification notification, making the presentPopoverFromRect method useless when applied handling this notification.
The way I solved it was by delaying the latter call as follows:
- (void)viewDidLoad
{
[super viewDidLoad];
popup = nil; //my ViewController with UITextField
popover = nil; //my UIPopoverController
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:#selector(resizePopup:)
name:UIKeyboardDidHideNotification
object:nil];
}
- (void)doDelayedResize
{
[popover presentPopoverFromRect:myButton.bounds inView:myButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
- (void)resizePopup:(NSNotification*)note
{
[self performSelector:#selector(doDelayedResize) withObject:nil afterDelay:0.01];
}
I answered a very similar question here: UIPopoverController's view controller gets resized after keyboard disappears
The way I got around it was to observe the keyboard disappearing in the controller which controls the UIPopoverController:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(presentSearchPopover) name:UIKeyboardDidHideNotification object:nil];
And then in -presentSearchPopover, present the UIPopoverController again (it's quite a seamless transition):
- (void)presentSearchPopover
{
self.searchPopoverController.popoverContentSize = CGSizeMake(width, height));
[self.searchPopoverController presentPopoverFromRect:someRect) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
Don't forget to remove the observer in -dealloc or similar too:
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
[super dealloc];
}
I found an answer for this.It was a bug with the top arrow of popover.If I use the left arrow direction for popover, everything works fine.
I ran into this issue as well - specifically, the popover wasn't growing back to its pre-keyboard size after tapping away from the popover. (The popover would grow back if the user dismissed the keyboard directly or the popover's view controller resigned first responder).
Unfortunately, I have to use the top arrow direction for the popover due to the UI's layout. To solve this, the view controller responsible for the popover implements - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController. For example:
#interface MyController : UIViewController <UIPopoverControllerDelegate>
{
// ...
}
//...
#end
Set that controller as the popover's delegate:
MyPopoverViewController *popoverVC = [[MyPopoverViewController alloc] init];
UIPopoverController *myPopover = [[UIPopoverController alloc] initWithContentViewController:popoverVC];
myPopover.delegate = self;
// Hang on to popoverVC, myPopover or release them as desired...
In addition, my popover's view controller sets its contentSizeForViewInPopover property to the desired size:
#implementation MyPopoverViewController
- (id)init
{
self = [super init];
if (self)
{
// ...
self.contentSizeForViewInPopover = CGSizeMake(320, 400); // desired size
}
return self;
}
When the keyboard causes the popover to shrink, it affects the popover's popoverContentSize and not its view controller's contentSizeForViewInPopover. Therefore, reset popoverContentSize in MyController's delegate method:
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
// Check if popoverController is valid, the popover you want, etc
popoverController.popoverContentSize = popoverController.contentViewController.contentSizeForViewInPopover;
}
Here is my solution:
1. Register for keyboard Notifications (UIKeyboardWillShowNotification, UIKeyboardWillHideNotification)
2. Create local variables:
CGSize _currentPopoverContentSize; //if you want to have custom size for popover
UIView *_currentPopoverSender; //to remember from wich view you will present popover
BOOL _keyboardIsShown; //enable in keyboardWillShow, and disable in keyboardWillHide
3. In my presentPopover method:
- (void)presentPopoverControllerWithSize:(CGSize)size fromView:(UIView *)sender{
MyController *controller = [[[MyController alloc] init] autorelease];
if (self.popover)
{
[_popover release];
_popover = nil;
}
_popover = [[UIPopoverController alloc] initWithContentViewController:controller];
_popover.popoverContentSize = size;
_popover.delegate = self;
//checking if keyboard is shown - if NO, than present popover, if YES - just `resignFirstResponder` for your _`activeTextField`(you can set it in -textFieldDidBeginEditing: and nullify in -textFieldDidEndEditing:)
if (!_keyboardIsShown)
{
[_popover presentPopoverFromRect:[sender bounds]
inView:sender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}
else
{
[_activeTextField resignFirstResponder];
}
_currentPopoverContentSize = size;
_currentPopoverSender = sender;
}
4. Than:
- (void)keyboardWillBeHidden:(NSNotification*)aNotification{
[UIView animateWithDuration:0.3
animations:^{
//do some stuff
[self.scrollView setContentSize:_scrollViewContentSize];
} completion:^(BOOL finished) {
if (_popover && _currentPopoverSender)
{
[_popover presentPopoverFromRect:[_currentPopoverSender bounds]
inView:_currentPopoverSender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}
}];
_keyboardIsShown = NO;
}
Hi After going through the forum, I don't think it's a bug after playing with frame sizes a lot, working on IOS 4,5,6,7 it's the same behaviour.
The solution for me was to:
1) Go into the designer by
2) Opening the XIB ViewController that is causing the problem (i.e. the PopOver one).
3) Click to select it's VIEW.
4) Uncheck "AutoResizeSubviews"
5) When loading the PopOver in code, make sure you do:
6) Your_Popup_Window.popoverContentSize = Your_ViewController.view.bounds.size;
I hope this helps.
Kind Regards
Heider Sati