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.
Related
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];
}
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;
}
I'm pretty new with the iOS stuff, and thought I understood passing data to a view controller. Apparently not. I am trying to pass image data from a parent ViewController to a child ViewController that is presented modally. I think the problem has something to with the way objects are passed to a modally presented view controller instead of one pushed onto the navigation stack. Bellow is the code from the parent and the child related to the problems I am having.
From the Parent.m:
- (IBAction)sort:(id)sender {
SortSelectViewController *ssvc = [self.storyboard instantiateViewControllerWithIdentifier:#"sort"];
ssvc.backgroundImage = [self screenshot];
[self performSegueWithIdentifier:#"sort" sender:self];
//The segue is linked from my parent view controller to my child with the identifier "sort"
}
- (UIImage *) screenshot {
CGRect rect = CGRectMake(0, 20, 640, 1116);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, [UIScreen mainScreen].scale);
[self.view drawViewHierarchyInRect:rect afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
return image;
}
This is in my Child.h
#property (nonatomic, strong) UIImage *backgroundImage;
This is my Child.m:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(#"%#", self.backgroundImage);
//This log will return nil when the program is run - clear sign data is not being correctly passed
self.backgroundImage = [self.backgroundImage applyDarkEffect];
self.imageView.image = self.backgroundImage;
}
I have imported my child view controller into my parent class
Your code (original question) is conflating direct instantiation of view controller and storyboard segues. When you use a storyboard segue, the VC is instantiated automatically for you. You access it as the "destination view controller" in the segue in "prepareForSegue:" method.
What's happening is that you instantiate a view controller, set the image, then… it gets thrown away and ignored (the entire vc).
Next, you initiate a segue, which iOS handles by instantiating another, different view controller. It's this view controller that iOS is presenting.
So: if you're going to use a Storyboard segue, iOS instantiates the VC for you. Don't instantiate one yourself, because there's no way to link the one you instantiate into the iOS segue handling. The one you instantiate is an irrelevant extra that gets ignored.
try Like this By using Story Bord Must use combination of two Methods performSegueWithIdentifier: *prepareForSegue:*
- (IBAction)sort:(id)sender {
[self performSegueWithIdentifier:#"sort" sender:self];
//The segue is linked from my parent view controller to my child with the identifier "sort"
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"sort"])
{
SortSelectViewController *ssvc = [segue destinationViewController];
ssvc.backgroundImage = [self screenshot];
}
}
- (UIImage *) screenshot {
//return normal image
return [UIImage imagenamed:"imagename.png"];
}
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.
I've been trying to use the new xcode 5 storyboard paradigm and not create .xib files specifically. I've got two VCs - the first was created by Xcode, the second was created by dropping a UIViewController into InterfaceBuilder.
My issue is that even though I've given my second VC a custom class and imported the headers into the first VC, when I create the second VC programatically it doesn't conform to the design I set in InterfaceBuilder. The first one does.
My code to create the second VC goes something like this (it's inside an ImagePickerControllerDelegate method) :
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *chosenImage = [info objectForKey:UIImagePickerControllerEditedImage];
NCPhotoViewController *newController = [[NCPhotoViewController alloc] init];
newController.theImage = chosenImage;
** NEW CODE newController.theImageView.image = newController.theImage;
[self dismissViewControllerAnimated:YES completion:^{
[self presentViewController:newController animated:YES completion:NULL];
}];
...which seems fine, and does what I want it to - brings up a new view controller. Thing is, it doesn't load with the layout I set in IB. I tried exchanging the the alloc] init] method to initWithNibName:bundle: but realised that I didn't a nib... is there a way I can make this connection in IB without creating a .xib file, or have I misunderstood the new flow of Xcode 5? I'm aware that there's a Storyboard ID attribute in the Identity Inspector, but how do I use that to my advantage? I don't want to do things "the old way" if they're not being put there by default...
TL;DR - I'd like my IB laid-out ViewController to look the way it's intended when called programatically in Xcode 5 default storyboard flow.
Added some code to make the imageview of the new viewcontroller have an image, but it doesn't appear...
EDIT: I had to add self.theImageView.image = theImage; in the viewDidLoad method in my new viewcontroller.h file - but shouldn't it already do that with the code I've written?
If you setup your controller in storyboard you should load it from it. If your code is already in some controller from the same storyboard you can do it the following way:
UIStoryboard *sb = self.storyboard;
NCPhotoViewController * newController = [sb instantiateViewControllerWithIdentifier:#"SomeIdentifier"];
...
You also need to set Storyboard ID for your view controller to "SomeIdentifier" so storyboard will know which controller to instantiate. Here's how it will look in Utilities pane in IB: