3

Simple problem, I have defined a UIImageView, called bigImageView in a UIViewController using the storyboard, It's declared in the h file of that UIViewController as follows:

 @property (retain, nonatomic) IBOutlet UIImageView *bigImageView;

on my appDelegate I init the UIViewController as follows:

imageViewController = [storyboard instantiateViewControllerWithIdentifier:@"chosenImageController"];

this calls initWithCoder on my UIViewController m file:

-(id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        // Custom initialization
    }
    return self;
}

This function is only called once so there's no double init. However, later, when I check my bigImageView pointer, it's still nil.

Isn't the init supposed to allocate memory to it? I think that's why when I try to set this UIImageview to hold a UIImage it doesn't display the image Thanks

Alon_T
  • 1,430
  • 4
  • 26
  • 47
  • When does your viewDidLoad or viewWillApear methods for this VC get called? – Robert J. Clegg Mar 30 '14 at 06:18
  • @Tander, I get to this UIViewController, from another one, in which I have a button that invokes a function that calls [self.navigationController pushViewController:imageViewController animated:YES ]; – Alon_T Mar 30 '14 at 06:20

2 Answers2

0

It's all working how it's meant to. First every object in the nib/storyboard gets alloc/init called on them, then all the connections are made, and then viewDidLoad is called.

You need to wait for - (void)viewDidLoad to be called on your controller, and then bigImageView should be set. If it's not set then you did something wrong in the storyboard.

init methods are not responsible for allocating any memory. All memory is allocated by the alloc method which is always called before init. Alloc will fill all your instance variables with nil/NULL/0 values, and then init gives the chance to assign initial values to each one (based on the contents of the NSCoder object usually, but it's up to you to decide what should be done).

For IB outlets however, those are setup by the nib loading process after init.

EDIT:

// ViewControllerA.m:
imageViewController = [storyboard instantiateViewControllerWithIdentifier:@"chosenImageController"];
imageViewController.image = imageToShow;

// ViewControllerB.h
@property (retain) NSImage *image;
@property (retain, nonatomic) IBOutlet UIImageView *bigImageView;

// ViewControllerB.m
- (void)viewDidLoad
{
  self.bigImageView.image = self.image;

  [super viewDidLoad];
}
Abhi Beckert
  • 32,787
  • 12
  • 83
  • 110
  • I have a viewcontrollerA that appears before that one does, and on viewcontrollerA I select an image, which in turn supposed to set the image using delegate before I show my second, imageViewController. – Alon_T Mar 30 '14 at 06:24
  • @Alon_T I've updated my answer to show you how to provide the image to the next view controller. Note that all of this code will execute before the GPU does anything. – Abhi Beckert Mar 30 '14 at 06:30
-2

You don't need to define initWithCoder, since you have no custom logic in there. I would delete that boilerplate code.

Here is what I would check:

  1. In the storyboard, ensure that the class of the view controller is set properly.
  2. Ensure that the outlet is hooked up properly in the storyboard by looking for a circle near your @property. It should be a filled in circle, not an outline of a circle.
  3. Make sure you are reading the value only after viewDidLoad is called. Apple's only guarantee is that the outlet is set after this method call.

Update: It sounds like you want to access the image view before the view is loaded. There is no way to do this. One hack is to call viewController.view which will force the view to load, but there are many reasons why you should not do this.

A better approach would be to implement properties on your view controller which work for both when the view is not loaded and when the view is loaded. You can see an example of an elegant solution in this question. Notice how if the view is loaded, the photographerLabel will get set via the didSet method. On the other hand, if the view is not loaded, it will get set via the viewDidLoad method. For an Objective-C version of that code or for more details, see the linked video in that question.

Community
  • 1
  • 1
Senseful
  • 86,719
  • 67
  • 308
  • 465
  • initWithCoder was defined for the sake of debugging – Alon_T Mar 30 '14 at 06:21
  • if the name of the class wasn't right the debugger wouldn't get there ;) – Alon_T Mar 30 '14 at 06:21
  • I see about the viewDidLoad. But that is called only when actually showing that controller. I want to be able to handle the values ther (such as set a pre-displayed image) before I show that controller – Alon_T Mar 30 '14 at 06:23
  • @Alon_T: viewDidLoad is called before viewWillAppear and viewDidAppear. You should be able to make all your customizations there. – Senseful Mar 30 '14 at 06:24
  • @Alon_T `viewDidLoad` is called after everything loads but before any screen drawing instructions are sent to the GPU. So you can do stuff in there without the user seeing the state prior to viewDidLoad. – Abhi Beckert Mar 30 '14 at 06:24
  • I want to be able to set an image in my controller regardless of showing my window. viewDidLoad is only invoked when I push that view to the stack. That's not what I want :( – Alon_T Mar 30 '14 at 06:28
  • @Alon_T setting the image to your controller is a separate action from providing the image to the image view. Don't setup the image view until it's about to be presented on the screen, it's generally a waste of RAM to have views that aren't currently visible. RAM is in short supply on iOS, your app will be terminated in the background more often if you do that. – Abhi Beckert Mar 30 '14 at 06:34