CGIImage is nil after a segue - ios

I have a prepareForSegue that passes an image like this to the next viewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
WizardPreview *controller = [segue destinationViewController];
controller.myPicture = myPicture;
}
On the viewWillAppear of the viewController being presented I have a like like this
CGImageRef imageRef = [self.myPicture CGImage];
the result is nil
The strange part is that self.myPicture is not nil, but self.myPicture.CGImage is.
Any reason for that?
NOTE: myPicture is not nil when it is passed and even from viewWillAppear, I test and I see that self.myPicture is not nil.
NOTE 2: this is a code compiled for iOS 7 running on an iPhone with iOS 8.

You haven't posted enough code to say for sure. The three most likely options are:
If myPicture is nil in the prepareForSegure:sender: method
If WizardPreview's myPicture property is weak
If the UIImage is not backed by a CGImage (for example, if it's backed by a CIImage)
If #3 is true, you can create a CGImage directly from a CIImage (sample code here).

Related

Incompatible pointer type on using segue to pass image? objective c Xcode

when i trying to use segue to change image on a second viewController, i got a problem which saying:
Incompatible pointer type assigning to "UIimage*_Nullable" to "NSArray"
and my code is like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"the_segue"]){
SecondViewController *transferViewController = [segue destinationViewController];
transferViewController.theimageView.image=#"photo.jpg";
}
}
can anyone help me out for telling me how to solve it , thanks!
You are assigning theimageView's image property (which is a UIImage) to a string.
I think what you want is transferViewController.theimageView.image = [UIImage imageNamed:#"photo.jpg"];
You are using a String to represent a UIImage in that case the compiler is giving you the warning : "Incompatible pointer type assigning to "UIimage*_Nullable" to "NSArray"
just do:-
transferViewController.theimageView.image = [UIImage imageNamed:#"ImageName"];
or
[transferViewController.theimageView setImage:[UIImage imageNamed:#"ImageName"]];
also you dont need to mention the extention of the image you just mention the name the extention is need when there are two image's having similar name but have different extentions.

Unable to set UIImage, always returns nil

This is probably a ridiculous question but I just can't figure it out for the life of me. I have a class which subclasses NSObject which has a property called image setup, like this:
#property (strong, nonatomic) UIImage *image;
Somewhere else I initialize the class and attempt to set the image in the class, like this:
UIImage *image = [UIImage imageNamed:#"Test"];
Class *item = [[Class alloc] init];
item.image = image;
But when I try to call item.image it is always nil.
The image called Test is in the project and is used elsewhere so I know it has access to the image, but for some reason it isn't being copied to the instance of my class. I have put NSLog messages and breakpoints directly after setting the image which have shown it to be nil as well as using commands via the debugger which have also shown the image in the class to be nil while the UIImage I create to copy is not nil.
I know I am doing something wrong but I have searched and can't figure out what it is.
Thanks for looking, any help is much appreciated.
edit:
I am trying to access the image from a method inside of the class.
- (void)save {
if (self.image != nil) {
// do some stuff
} else {
NSLog(#"image is nil");
}
}
And it is always coming up nil.
edit 2:
Thanks again everyone. I figured out what the problem was. I was overriding the setters/getters which was causing the issue.
Is it a .png file? Try doing it like this:
UIImage *image = [UIImage imageNamed:#"Test.png"];

prepareForSegue destination controller property not being set

Here's my prepareForSegue:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqual:#"cameraToRollsSegue"]){
ALRollsTableViewController *rollsTableViewController = (ALRollsTableViewController *)[segue destinationViewController];
Camera *c = [self.fetchedResultsController objectAtIndexPath:[self.tableView indexPathForSelectedRow]];
NSLog(#"CAMERA FROM INSIDE PREPARE FOR SEQUE: %#", c);
rollsTableViewController.selectedCamera = c;
}
}
I verify that the camera is not null with NSLog:
CAMERA FROM INSIDE PREPARE FOR SEQUE: <Camera: 0x8dc1400> (entity: Camera; id: 0x8dafba0 <x-coredata://A415F856-5F21-4F08-9CAB-4B2A023B55C3/Camera/p1> ;
ALRollsTableViewController viewDidLoad:
- (void)viewDidLoad
{
NSLog (#"ROLLS TABLE VIEW CONTROLLER : viewDidLoad!");
NSLog(#"(selected camera = %#", self.selectedCamera);
}
results in:
ROLLS TABLE VIEW CONTROLLER : viewDidLoad!
(selected camera = (null)
What might I be doing wrong here that the property is not being set?
UPDATE
With matt's help I've determined that the instance of my destination view controller in my prepareForSeque does not match the actual destination view controller:
rollsTableViewController FROM SEGUE: <ALRollViewController: 0x8d90bf0>
rollsTableViewController FROM viewDidLoad in rollsTableViewController: <ALRollsTableViewController: 0x8c5ab00>
I don't know why this is the case or what to do to fix it.
Post-chat summary:
Well, it was complicated! But basically you were saying this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqual:#"cameraToRollsSegue"]){
ALRollsTableViewController *rollsTableViewController = (ALRollsTableViewController *)[segue destinationViewController];
// ...
}
The problem was that [segue destinationViewController] was not an ALRollsTableViewController. Thus you were not talking to the instance you thought you were talking to, and you were not talking to an instance of the class you thought you were talking to.
The amazing thing is that your code didn't crash when it ran. You were saying this:
rollsTableViewController.selectedCamera = c;
But rollsTableViewController was not in fact an ALRollsTableViewController. You lied to the compiler when you cast incorrectly. Yet you didn't crash when that line ran. Why not? It's because you've got lots of classes with #property selectedCamera! So you were setting the property of a different class. But a property with that same name did exist in that class, so you didn't crash. Thus you didn't discover that this was the wrong class and the wrong instance.

Getting NSData from UIImage object that contains CGImage

In order to upload an image file to my server, I need to get it's NSData. I am having trouble doing this right now, because my UIImage contains a CGImage.
Let me show you how I am doing things. When a user takes a photo, this is what I do with the captured photo:
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [[UIImage alloc]initWithData:imageData];
_subLayer = [CALayer layer];
image = [self selfieCorrection:image];
image = [self rotate:image andOrientation:image.imageOrientation];
CGRect cropRectFinal = CGRectMake(cropRect.origin.x, 140, cropRect.size.width, cropRect.size.height);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRectFinal);
_subLayer.contents = (id)[UIImage imageWithCGImage:imageRef].CGImage;
In the above code, I create a UIImage, and initialize it with the imageData object. I also create a layer object called _subLayer that will display the final image on the screen. The image's orientation is then rotated and corrected, and then I setup a CGRect to crop the part of the image I want to keep.
The most important part are the last 2 statements. I create a CGImageRef called imageRef using the original UIImage. Then, in the last statement, I set the contents property of _subLayer to equal my final image.
A little further down in this same view controller, inside of an IBAction I have the following statement which helps me pass the image to my next view controller: sendFriendsVC.finalPhotoToSend = _subLayer.contents;
finalPhotoToSend is a property that I have setup in the header file of my next view controller like this:
#property (nonatomic, retain) UIImage *finalPhotoToSend;
The data is successfully passed when I segue to the next view controller, but when I NSLog finalPhotoToSend, even though it is a UIImage, it prints as this to the console:
<CGImage 0x1563dac0>
In order to upload photos to my backend server service, it requires me to create an object using NSData. I have tried using these 2 methods to get the NSData out of the finalPhotoToSend object:
NSData *imageData = UIImageJPEGRepresentation(finalPhotoToSend, 0.7);
and
NSData *imageData = UIImagePNGRepresentation(finalPhotoToSend);
But those always give me the following error in xcode:
NSInvalidArgumentException', reason: '-[__NSCFType CGImage]: unrecognized selector sent to instance
I am not sure what to do. Is there a different method I should be using to get NSData out of my UIImage since it is technically holding a CGImage? Should I be doing something differently before I even pass the data to my next view controller?
Edit for Michael:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:self {
if ([segue.identifier isEqualToString:#"mediaCaptureToSendToFriendsSegue"]) {
SendToFriendsViewController *sendFriendsVC = segue.destinationViewController;
sendFriendsVC.finalPhotoToSend = _subLayer.contents;
}
}
I just figured it out. Here's what I ended up using for the IBAction method implementation:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:self {
if ([segue.identifier isEqualToString:#"mediaCaptureToSendToFriendsSegue"]) {
SendToFriendsViewController *sendFriendsVC = segue.destinationViewController;
UIImage* image2 = [UIImage imageWithCGImage:(__bridge CGImageRef)(_subLayer.contents)];
sendFriendsVC.finalPhotoToSend = image2;
}
}
I'm new to objective-c and not really entirely sure what the following statement is even doing:
UIImage* image2 = [UIImage imageWithCGImage:(__bridge CGImageRef)(_subLayer.contents)];
But xcode suggested it and it works. Now on the next view controller, the finalPhotoToSend object NSLogs as a UIImage instead of a CGImage.
Better answer:
You need to truly set a UIImage object (and not a CGImage pointer) to a property that you've declared to be a UIImage object.
Original:
if "finalPhotoToSend" is a property, you should be doing:
NSData *imageData = UIImageJPEGRepresentation(self.finalPhotoToSend, 0.7);
and not:
NSData *imageData = UIImageJPEGRepresentation(finalPhotoToSend, 0.7);

Custom setter for segue not seeing the object I'm sending to it in iPhone Master/Detail storyboard

Basically, I'm trying to send an object from the master view to the detail view by way of a custom setter. However, as soon as the setter gets called in the detail view, the app immediately crashes. I'm not too good at debugging, but I think it's because the object isn't making it to the setter -- it's seeing it as nil. Could be wrong about that, though.
Here's the code for the segue in the master view:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
CCNewsItem *theNewsItem = self.listOfNewsItems[indexPath.row];
NSLog(#"Preparing to pass: %#", theNewsItem);
[[segue destinationViewController] setSelectedNewsItem:theNewsItem];
}
}
And here it is for the setter in the detail view:
- (void)setSelectedNewsItem:(CCNewsItem *)newItem
{
if (self.selectedNewsItem != newItem) {
self.selectedNewsItem = newItem;
// Update the view.
[self configureView];
}
}
It crashes exactly on the - (void)setSelectedNewsItem:(CCNewsItem *)newItem line. I've made super-sure that the object being passed is valid (I log it to double check, and all seems well), but it seems that it either isn't making it to the setter or it's somehow exploding when it hits it.
Any ideas? Thanks!
As requested, here's the logs/exception
This is what my NSLog shows on the object I'm trying to pass:
2013-11-02 14:18:23.660 Curtis Consulting[14862:60b] Preparing to pass: <CCNewsItem: 0x14e70580>
When the app stops on the setter's first line (I'm not sure why; I have all breakpoints disabled), it shows the values of newItem (the passed object) as:
newItem CCNewsItem * nil 0x00000000
NSObject NSObject
_headline NSString * nil
_body NSString * nil
_url NSURL * nil
Edit 2
Since, as near as I can tell, there is no way to copy the error it's showing (in a green bar at the right, but I don't have any breakpoints turned on), here's my transcription of it:
Thread 1: EXC_BAD_ACCESS (code=2, address=0x27c84ff8)
In your setter method change:
if (self.selectedNewsItem != newItem) {
self.selectedNewsItem = newItem;
to
if (_selectedNewsItem != newItem) {
_selectedNewsItem = newItem;
Because your current code has an infinite loop calling the accessor method. Be sure you know what using self. means...

Resources