set UIImageView.image in prepareForSegue - objective-c

I want to segue to a photoViewController that has an UIImageView.
In flickrTVC, I say:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showPhoto"])
{
photoViewController *vc = [segue destinationViewController];
UIImage *photo = [UIImage imageWithContentsOfFile:#"images/en.jpeg"];
[vc setDisplayedPhoto:photo];
}
}
and the setDisplayedPhoto method's implementation is:
-(void)setDisplayedPhoto:(UIImage *)image
{
[_imageView setImage:image]; //#property (nonatomic, strong) IBOutlet UIImageView *imageView;
}
But when I do segue, the UIImageView is white... Why could this be?

Your destination view controller hasn't loaded its view hierarchy by the time your source view controller receives the prepareForSegue:sender: message. So your destination VC's _imageView variable is nil.
The recommended approach is to store the image (or, probably even better, the image file name) as a property of the destination VC, and then set the image view's image in the destination VC's viewDidLoad or viewWillAppear: method.

Call [vc view] before setting the o of the view

Related

set navigationController's rootViewController as delegate

My problem may be one of technique instead of a misunderstanding of how controllers and delegates are set up. That is, maybe I should be doing all a different way...
In any event, I have a storyboard setup with a mainViewController. In it there's a UIButton which, when clicked, segues to a popover. The popover's content view controller is a UINavigationController who's rootViewController is, say, MyViewController.
I'm trying to make the mainViewController a delegate of MyViewController and am doing so in prepareForSegue:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:(#"popSleepSegue")] || [segue.identifier isEqualToString:(#"popAlarmSegue")])
{
UIStoryboardPopoverSegue *popSegue = (UIStoryboardPopoverSegue *)segue;
popSegue.popoverController.delegate = self;
popSegue.popoverController.passthroughViews = [NSArray arrayWithObject:self.view];
if ([segue.identifier isEqualToString:#"popAlarmSegue"])
{
if ([[segue destinationViewController] isKindOfClass:[UINavigationController class]])
{
UINavigationController *uNC = (UINavigationController *)[segue destinationViewController];
MyViewController *aVC = (MyViewController *)uNC.topViewController;
aVC.popController = popSegue.popoverController;
aVC.delegate = self;
}
}
}
}
The [self.delegate class] is coming up as null in an NSLog when MyViewController loads. And, naturally, the delegate callback isn't received in the mainViewController.
Essentially, I'm trying to mimic the behavior of Apple's Calendar app on the iPad.
I'm trying to use delegation to pass data upstream as per the idiom. The trick is that I'm trying to set the delegate through a UINavigationController which is the content view of a popover. Sounds too complex. Maybe there's another idiom?
In the meantime, I'm going to give NSNotificationCenter a whirl.
You have to potential 'if' statements which can not be true:
if ([segue.identifier isEqualToString:#"popAlarmSegue"])
{
if ([[segue destinationViewController] isKindOfClass:[UINavigationController class]])
{
From the look of your code, you should get the controller drilling inside the content controller in the PopOver,not the destination viewController from the segue. As it seems the second 'if' is not true.
You would need to add:
if ([[popSegue.popoverController contentViewController] isKindOfClass:[UINavigationController class]])
{
UINavigationController *uNC = (UINavigationController *)popSegue.popoverController;
MyViewController *aVC = (MyViewController *)uNC.topViewController;
aVC.popController = popSegue.popoverController;
aVC.delegate = self;
}

UIImageView not setting image

Im trying to set a UIImageView from a segue, and for some reason the image is not getting set..
Heres the .h files of my class that subclassed a UIViewController
#interface PhotoDisplayViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *photoView;
-(void)setPhoto:(UIImage *)photo;
#end
and heres the setPhoto
-(void)setPhoto:(UIImage *)photo{
NSLog(#"PHOTO %#", photo);
_photoView.image = photo;
NSLog(#"MYPHOTO %#", _photoView.image);
}
when i call setPhoto from prepare for segue, i see this in the console
2012-12-16 13:26:22.129 TestApp[2183:907] PHOTO <UIImage: 0x1fd7cd80>
2012-12-16 13:26:22.130 TestApp[2183:907] MYPHOTO (null)
Why is this happening?
It looks like _photoView is probably nil. It may not be set when loading the nib. Make sure you've wired it up properly in IB. Or perhaps you are calling -setPhoto: before the view has loaded.
I would advise you to change the weak to strong and take a look on this link.
Objective-C - weak property - getter autoreleases (Automatic Reference Counting)
I think you called setPhoto: method as following. In this situation, first setPhoto: is called and after that viewDidLoad method is called in PhotoDisplayViewController. That's why photoView is nil. Actually viewDidLoad method should be called in PhotoDisplayViewController.So you should change the code slightly.
-(void)someActionMethod{
[self performSegueWithIdentifier:yourIdentifier sender:nil];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:yourIdentifier]) {
photoDisplayVC = [segue destinationViewController];//photoDisplayVC is a object of PhotoDisplayViewController
[photoDisplayVC setPhoto:imageObject];
}
The change Code: In this situation first viewDidLoad method is called and after that setPhoto: method is called in PhotoDisplayViewController. Then you will get image.
-(void)someActionMethod{
[self performSegueWithIdentifier:yourIdentifier sender:nil];
[photoDisplayVC setPhoto:imageObject];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:yourIdentifier]) {
photoDisplayVC = [segue destinationViewController];//photoDisplayVC is a object of PhotoDisplayViewController
}
I think it will be helpful to you.

How to pass an uiimage to another view controller?

How to pass the uiimage selected in uiimagepickercontroller in MainViewController to SecondViewController? It did push to the SecondViewController, however the uiimage is empty.
I've searched through the web, tried with the solutions but still cannot get it work.
photoImage is the uiimageview I've declared in SecondViewController.
- (void)imagePickerController:(UIImagePickerController *) picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissModalViewControllerAnimated:YES];
SecondViewController *secondVC = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[secondVC.photoImage setImage:[info objectForKey:#"UIImagePickerControllerEditedImage"]];
[self.navigationController pushViewController:secondVC animated:YES];
[secondVC release];
}
A UIImageView in your second view controller doesn't exist until the viewDidLoad method of that controller is called. Put a property into SecondViewController that holds a UIImage, store the reference to the image you want to use in it when you push the view controller (instead of trying to set the image view), and then move your setImage: call into the second view controller's `viewDidLoad``.
Create a shared class that will store the image, and access it wherever you want.
In MainViewController assign that image in that shared class' ivar, and in SecondViewController access it.
Edit :
Below code shows how to implement shared class, this may not be syntactically correct, because currently I am not using mac, so I cant complile.
#interface SomeManager : NSObject
+(id)myImage;
#end
#implementation SomeManager
+(id)myImage{
static id myImage= nil;
#synchronized([self class]){
if (myImage== nil) {
myImage= //put your image here;
}
}
return myImage;
}
#end

Is there anyway to know where a popover was presented from?

I'm writing an iPad app and one of my screens has lots of small buttons that when pressed will display one sentence of text in a popover originating from that button. Currently all popovers are created using the storyboard and I store the popover controller in my UIViewController as such:
#property (nonatomic, strong) UIPopoverController *myPopoverController;
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue isKindOfClass:[UIStoryboardPopoverSegue class]])
{
UIStoryboardPopoverSegue *popoverSegue = (UIStoryboardPopoverSegue *)segue;
self.myPopoverController = popoverSegue.popoverController;
}
}
However, I can't figure out a good way to deal with rotation. Right my didRotate method looks like so:
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if (self.myPopoverController)
{
[self.myPopoverController dismissPopoverAnimated: NO];
[self.myPopoverController presentPopoverFromRect:?????? inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:NO];
}
}
However, I don't know where to present the popovers from given that they could have originated from any of the small buttons on my screen. Any suggestions? Remember that these are VERY simple popovers, thus a whole bunch of new code is not ideal.
Your best bet may be to make another property in your main view controller that keeps a reference to the button pressed. Something like:
#property (nonatomic, strong) UIPopoverController *myPopoverController;
#property (nonatomic, weak) UIView *popoverButton;
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue isKindOfClass:[UIStoryboardPopoverSegue class]])
{
UIStoryboardPopoverSegue *popoverSegue = (UIStoryboardPopoverSegue *)segue;
self.myPopoverController = popoverSegue.popoverController;
//The sender in prepareForSegue should be the view used to initiate the segue.
popoverButton = (UIView *)sender;
}
}
That done, you can modify your rotation code thusly:
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if (self.myPopoverController)
{
[self.myPopoverController dismissPopoverAnimated: NO];
[self.myPopoverController presentPopoverFromRect:popoverButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:NO];
}
}
Keeping a reference to the pressed button takes up no more resources that storing a pointer, and keeping the reference weak should avoid retain cycles (after all, your view controller does not own the button, the button's superview owns it).

(iOS) How can I Reuse an UIImageView in another View?

I have a view controller with a UIScrollView with a heap of UIImageViews as subviews. There is a segue to another view controller but i want to reuse the UIImages that are already in memory rather than load them again for efficiency's sake. But if I point my new UIImageView to an existing one, nothing shows up.
I had to use an intermediate pointer variable (imageViewPointer) as if I assign it directly in the prepareForSegue method, the NSLog's from each view controller would show different addresses. This workaround NSLogs show the same address but still nothing shows up.
If I use reassign the .image property instead, the image shows up but the images from the first view controller are load asynchronously so the .image property might change.
In the first view controller
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NextViewController *nextViewController = [segue destinationViewController];
nextViewController.imageViewPointer = [[myScrollView subviews] objectAtIndex:myIndex];
NSLog(#"%#", [[myScrollView subviews] objectAtIndex:myIndex]);
}
In the second view controller
#interface nextViewController : UIViewController
#property (retain, nonatomic) IBOutlet UIImageView *imageView;
#property (retain, nonatomic) UIImageView *imageViewPointer;
#implementation nextViewController
#synthesize imageView, imageViewPointer;
{
self.imageView = self.imageViewPointer;
// [self.imageView setNeedsDisplay]; Doesn't help
NSLog(#"IMAGE VIEW POINTER = %#", self.imageViewPointer);
NSLog(#"IMAGE VIEW = %#", self.imageView);
[super viewDidLoad];
}
If you simply assign a view like that, it won't appear in the view hierarchy of your current view controller's view. You'll need to do something like:
[self.view addSubview: imageView];
However, I wouldn't recommend that. It is better to just assign the image of the view to the image of the other view.
self.imageView.image = self.imageViewPointer.image;
Either you reuse the UIImage or the method you are doing is a bit wrong as you are assigning the imageViewPointer to imageView which is(imageViewPointer) not a subview of your view controller's view. So add subview imageViewPointer or imageView after assigning imageViewPointer.