Trying to set image in the PresentViewController with ImagePickerController - ios

Ive got a storyboard with 2 ViewControllers, the first ViewController got a button to pick a photo from the photo album. The second ViewController has a ImageView.
the outcome is a black screen.
This is the delegate method:
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self dismissViewControllerAnimated:NO completion:nil];
UIImage * selectedIMG = [info objectForKey:UIImagePickerControllerOriginalImage];
VCImageEditingViewController *ieVC = [self.storyboard instantiateViewControllerWithIdentifier:#"VCImageEditingViewController"];
ieVC.selectedIMG = selectedIMG;
[self presentViewController: ieVC animated:NO completion:nil];
}
In the VCImageEditingViewController.m:
-(void)loadView
{
if (self.selectedIMG) {
self.imageDisplayed.image = self.selectedIMG;
}
else{
UIImage *image = [UIImage imageNamed:#"hat.jpg"];
self.imageDisplayed.image = image;
}
}
Even when i change the if statement to show the "hat" photo in both cases it shows me a black screen, so i'm pretty sure its got to do with the image picker.
Thank you for your help.

Two things:
You are using loadView when you should be using viewDidLoad and calling [super viewDidLoad]
The line: [self.view sendSubviewToBack:self.imageDisplayed]; doesn't display the image on the image view, it should be: self.imageDisplayed.image = self.selectedIMG;

I think the problem is that you are overriding loadView, for a controller you set up in the storyboard.
The docs say for loadView:
If you use Interface Builder to create your views and initialize the view controller, you must not override this method.
....
If you want to perform any additional initialization of your views, do so in the viewDidLoad method.
Try to override -(void) viewDidLoad instead, and set the image for the ImageView (assuming that you have set up self.imageDisplay up as a View Controller's view's subview) there.

Related

Load Image In Container View On ViewDidLoad

I have a question regarding view hierarchy:
I currently have a HomeViewController that is loaded into view after a login screen. The HomeViewController has a ContainerView, which is embedded with a SubViewController. This container is initially hidden when the home view is loaded. When I trigger an action (via a UIButton) to "unhide" the container, I am trying to have an image load in that SubViewController that was rendered in the HomeViewController during viewDidLoad.
The problem I am facing is that for whatever reason, I can not seem to have the image display in the SubViewController.
FYI: The way I am rendering this image is such:
Upon the HomeViewController's viewDidLoad, I am taking a screen shot programmatically of a UIView that is generated from saved user data. This UIView is displayed in the view of the HomeViewController.
When the user clicks a button, I am unhiding and now showing the SubViewController, the view embedded in the ContainerView.
I can not seem to get the screen shot image (saved as imageSS) to appear in the SubViewController. I have tried to suppress the viewDidLoad method for the SubViewController when the HomeViewController is loaded, then call the SubViewController viewDidLoad when the button is pressed to show it, but no luck there either.
This might be confusing but it should be easy - I am at a loss why I can't get this to work. If anyone can help me out I would appreciate it. Thanks!
Here is the code i am currently trying: this method is in the HomeViewController.m
- (void)takeScreenshot:(id)sender {
UIGraphicsBeginImageContextWithOptions(_homeRenderImage.bounds.size, NO, 0.0);
[_homeRenderImage drawViewHierarchyInRect:_homeRenderImage.bounds afterScreenUpdates:YES];
UIImage *imageSS = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
SubViewController *pvc = [[SubViewController alloc] init];
userImage = imageSS;
[pvc loadImage];
}
Here is the method I am using in the SubViewController.m:
NOTE: userImage is a shared property between these controllers. I have tested that this sharing works
- (void)loadImage {
_subImage.image = userImage;
}
I feel dumb - all I needed to do was to call the loadImage method in the viewWillAppear method:
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear: animated];
[self loadImage];
}

UIImagePicker only works with front camera on iPhone 6 plus

Using the following code:
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (!self.alreadyAppeared) {
[self performSelector:#selector(showCamera) withObject:nil afterDelay:0.3];
}
}
-(void)showCamera
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.showsCameraControls = YES;
picker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
picker.delegate = self;
[self presentViewController: picker animated:YES completion:NULL];
}
my app works perfectly. However if I change the
picker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
to
picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
I lose the image. The following code is how I capture the image and set an imageview within my app. I use a Nav controller to return to the app:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
self.cf.imageView.image = chosenImage;
NSLog(#"%#",chosenImage);
[picker dismissViewControllerAnimated:YES completion:NULL];
// pop back to previous controller
NSArray *myControllers = self.nc.viewControllers;
int previous = (int)myControllers.count - 2;
UIViewController *previousController = [myControllers objectAtIndex:previous];
[self.nc popToViewController:previousController animated:YES];
}
Again, this works just fine on my iPad and it works just fine using the front camera. Even when using the rear camera the chosen image (that I log) appears correct. Does anybody have any idea why the rear camera setting would have such an effect?
One other item: I get this very irritating message that has about 1,000 different explanations none of which get rid of the message:
Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.
When using the iPhone 6 and 6 plus, you must prevent your views from reloading each time you navigate away from the camera control (picker). My app uses a View Controller that creates a dynamic view which is a form. Each field on that form is pulled from a web service and becomes a subview of the form. That includes the camera field, which I use a viewcontroller and xib to build the field. The form view builds the entire form through a drawRect method. The camera field attempts to call that method each time it navigates away. I prevent it from reloading and that appears to have solved the issue.
A more standard app may create the camera field dynamically in viewDidAppear method of the main view controller. If you have the main view controller set as the delegate for the camera field, it will still call the viewDidAppear when it navigates away from the picker. That must be prevented or you will lose the image.
The really funny thing here is that this only happens on iPhone 6 and 6 plus. All other devices do not attempt to reload the views ... go figure.

Xcode - how to dismiss modal UIImageView?

Very new to iOS development. I'm trying to make an thing that will let me select a photo from the photo library, and display it. I'm using a storyboard with a navigation controller. I'm able to select and display the image just fine, but I can't figure out how to dismiss the imageview and return back to the image picker. I just get a fullscreen image and cant click anywhere to do anything. Code looks like this:
snapViewController.h
#import <UIKit/UIKit.h>
#interface snapViewController : UIViewController <UIImagePickerControllerDelegate,
UINavigationControllerDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *ImageView;
- (IBAction) done:(UIStoryboardSegue *)unwindsegue;
#end
My .m
snapViewController.m
#import "snapViewController.h"
#interface snapViewController ()
#end
#implementation snapViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (BOOL)prefersStatusBarHidden {
return YES;
[self setNeedsStatusBarAppearanceUpdate];
}
- (void) viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
if (self.ImageView.image == nil){
UIImagePickerController * imagePickerController = [UIImagePickerController new];
imagePickerController.modalPresentationStyle = UIModalPresentationCurrentContext;
imagePickerController.delegate = self;
[self presentViewController:imagePickerController animated:NO completion:nil];
}
else {
}
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
self.ImageView.image = image;
[self.ImageView setUserInteractionEnabled:YES];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction) done:(UIStoryboardSegue *)unwindsegue {
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Storyboard looks like this, I stuck a toolbar on the bottom of the UIImageView with a done button:
Do I need to bind the done button to the [self dismissViewControllerAnimated:YES completion:nil]; action? How can I do this? I've been struggling with this for a couple hours and can't figure it out. Thanks.
Read up a bit on views and windows and view controllers and stuff, came up with this:
- (IBAction)kill:(id)sender {
self.ImageView.image = nil;
[self viewDidAppear:TRUE];
[self dismissViewControllerAnimated:NO completion:nil];
}
I bound my done button to it and it looks like it works. It seems to be acceptable memory wise(opening and closing images multiple times doesn't ever make memory increase over what it was originally). It if this is not the right way to do it please let me know. Thanks.
Modal segues are very special compared to other segues in the sense that when you dismiss the new view controller, you call a method from the old one. The way it works is like this:
In the old view controller create a method of type (IBAction*) with argument (UiStoryBoardSegue*). Example:
-(IBAction*)done:(UIStoryBoardSegue*)segue{}
Then, in the story board, from your "Done" button in the new view controller control-drag to the green (left most) button in the line on the bottom of the new view controller (same view controller as the Done button), the method you created in the old view controller will popup, and you need to select it.
What will happen now is that once the done button is pressed, the modal will dismiss and will call the Done method on the old view controller
You are on the right track with your kill IBAction however there's a few things you don't need in there. You should not be calling viewDidAppear from an action. Let the OS manage all calls to viewDidLoad, willAppear, didAppear, etc.
If you want to remove the imageview's image from displaying, then you simply need to call self.imageView.image = nil;. You could then add another button and hook it up to an action to open the image picker modal and select a different image.
Remember that snapViewController is not a modal, it is simply the root view controller in the navigation stack that happens to have a full-screen image on it. The Navigation controller is a component that holds a bunch of view controllers -- it itself is never displayed to the user. That said, you do not need to dismiss snapViewController to reset the image, you should just need a done or kill action that looks like this:
- (IBAction)kill:(id)sender {
self.imageView.image = nil;
}

Best way to operate a UIImagePickerController from a custom UITableViewCell

I have a custom UITableViewCell declared thusly:
#interface ValveCell : UITableViewCell <UINavigationControllerDelegate,UIImagePickerControllerDelegate>
A button which hooks to the following method:
- (void) addPicture {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
// I have tried every possible value for the presentation style
picker.modalPresentationStyle = UIModalPresentationNone;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
// controller is a #property I added to my custom class
// it is the UIViewController that is the data source/delegate for the table view
[self.controller presentViewController: picker animated: YES completion: nil];
}
And the supporting delegate method:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissViewControllerAnimated:YES completion: nil];
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
if (chosenImage) {
[self.valve pushPhoto: chosenImage];}
}
There are two issues (at least) I'm having with this code:
Every time I click the button, I get the following warning in my transcript: "Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates." I've tried the various presentation styles. I don't know why this is happening, or what I need to do to make it go away.
It bothers me that I have to hand a controller to the cell (in my tableView:cellForRowAtIndexPath: method). I know walking the superView chain is frowned upon. Is there a no better way to get a controller to open it from? Or an alternate way of opening the picker that doesn't need a controller? Even something like self.tableView.delegate would work if cells but had a back pointer to their tableview.
UPDATE
Answer for #1 goes to #Jiten Parmar below. As for #2, I found the PPTopMostController pod which allowed me to use the code:
[UIViewController topMostController]
which worked like a charm.
"Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates."
The answer is that when your app is in the portrait mode and you open the image picker with landscape it will show this warning in the console, but no need to worry that, it is not critical for your app and no crash issue will be there.

pass UIImage between UITabBarControllers

i'm trying to pass an UIImage from one UIView in UITabBarController1 to another UIView in UINavigationController in UITabBarController2. In View1 i tried this:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
UploadModifyViewController *view2 = [self.storyboard instantiateViewControllerWithIdentifier:#"modify"];
UITabBarController *navBar = [self.storyboard instantiateViewControllerWithIdentifier:#"navBar"];
view2.imageView.image = image; //<-----
[self dismissModalViewControllerAnimated:NO];
[self presentModalViewController:navBar animated:YES];
}
Remember, view2 is in a NavigationController, and NavigationController is in a TabBarController. Extern Variable doesn't work, because these can't be used with UI Elements.
Posted this question here too, but still no solution.
In this forum i posted a screenshot for better understanding from where to where i try to pass the image.
It probably doesn't work because the imageView outlet is still nil at the time you are accessing it. A view controller doesn't load its view unless it has to, and only when it loads its view from the NIB/storyboard will it connect the outlets.
You should declare a separate UIImage property in UploadModifyViewController that you can then use in this place to assign the image to. Then, in UploadModifyViewController's viewDidLoad, assign the property's contents to the image view.

Resources