Say I have 2 controllers, BarViewController and FooViewController.
FooViewController has an outlet to a UIImageView called imageView:
@property (nonatomic, weak) UIImageView *imageView;
BarViewController has an outlet to a UIButton button. BarViewController has a segue from this button to FooViewController, called BarToFooSegue (done in storyboard).
When I run the following code, and call NSLog on FooViewController.imageView.image, the result is nil, and my image won't display. Why is this the case?
// code in BarViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"BarToFooSegue"]){
NSURL *photoUrl = @"http://www.randurl.com/someImage"; // assume valid url
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:photoUrl]];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[segue.destinationViewController setImageView:imageView];
}
}
I've tried setting FooViewController.imageView to strong instead of weak, but the problem remains:
@property (nonatomic, strong) UIImageView *imageView;
Running my debugger, I notice the imageView in FooViewController is updated correctly inside prepareForSegue: but then gets re-updated a few lines afterwards to some newly allocated imageView with @property image set to nil. I am not sure what part of the control flow is causing this because it happened in lines written in assembly language.
I got my code working by adding a UIImage property to FooViewController:
@property (nonatomic, strong) UIImage *myImage;
and changing prepareForSegue: in BarViewController to pass the image instead of the imageView:
// code in BarViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"BarToFooSegue"]){
NSURL *photoUrl = @"http://www.randurl.com/someImage"; // assume valid url
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:photoUrl]];
[segue.destinationViewController setMyImage:image];
}
and modifying viewWillAppear: in FooViewController:
- (void)viewWillAppear:(BOOL)animated{
[self.imageView setImage:self.myImage];
}
Call [segue.destinationViewController view];
before you set the image, this will cause the view hierarchy to be loaded and your outlets will then be set.
In prepareForSegue
outlets aren't defined yet--they're nil. You're sending a message to nil, which is perfectly fine and therefore doesn't give you an error, but in this case it can lead to unexpected behavior. You can solve it by creating a temporary UIImage property, and set your image view to that image in viewDidLoad or viewWillAppear.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With