Retrieving image from NSData - ios

I have a view controller that allows me to add a name, image, and date..the name and date are sent back to the table view controller and displayed..I then have a edit view controller that shows when a populated cell is clicked...
my save method:
-(IBAction)save:(id)sender {
NSData *imageData = UIImagePNGRepresentation(_imageview.image);
[self.currentPlayer setValue:imageData forkey:#"playerPic"];
[self.delegate addPlayerViewControllerDidSave];
}
my delegate is calling the save:&error so i wont paste that code
I believe this is working but my question is how do I have that image display on the edit view controller
my name and date information is passing but not the image
I have a UIImageView and I am attempting something like that but I understand those are two different pointer types and wont work
-(void)viewDidLoad {
firstnameTextField.text = [self.currentPlayer playerName];
editImage.image = [self.currentPlayer playerPic];
}
any help would be appreciated

You need to create a UIImage from your NSData object as follows:
[UIImage imageWithData:[self.currentPlayer playerPic]]

Related

How can I make different phone calls taken from a plist?

I know how to make a phone call, but I'm trying to call certain people depending on which table view cell is selected. I viewed this question but with no success. In my viewDidLoad method, I created a NSDictionary for the phone numbers:
NSString *path = [[NSBundle mainBundle] pathForResource:#"State" ofType:#"plist"];
// Load the file content and read the data into arrays
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
stateNum = [dict objectForKey:#"Phone"];
I then sent the number that was selected to my detail view controller in the prepareForSegue method:
destViewController.phoneName = [stateNum objectAtIndex:indexPath.row];
I created an IBAction method and successfully linked it to the button in my storyboard:
-(IBAction)phone
{
[[UIApplication sharedApplication]
openURL: [NSURL URLWithString:plistNum]];
}
plistNum is defined in my viewDidLoad method of the detail view controller as:
plistNum = [NSString stringWithFormat:#"tel:%#",stateName];
The app compiles and runs, but when I click the button nothing happens. It worked when I had tel:12345678901 in URLWithString but not now. If anyone has any suggestions I would be happy to listen. I am very, very new to this so if you could explain your answer I would appreciate it. Thanks.
Edit: #rmaddy helped me find my dumb mistake. I had used stateName in the plistNum String instead of phoneName. There were no messages on the console, the string I had created was just not a phone number. Also, I don't have a viewWillAppear method. Will creating this make the program smoother?

IOS/Objective-C/Core-data: How to detect if new image picked in picker controller

For a profile page, I let users choose an image if they want. Otherwise, the page displays a generic headshot. In the edit version of the page, it similarly shows the image they pick using the image picker controller or a generic headshot if they have never chosen one.
When I save in core data, if they have chosen image, I save the image as a file and save its name in core data. That is working.
However, if they have not chosen an image and the generic headshot is showing, I don't want to save anything--either an image or a value for pic name in core data.
Right now, I am grabbing the image name and contents from the view and discovered I am inadvertently saving the generic image view and also the generic image name in core data which causes problems down the line.
How can I grab the image and name if is a chosen image but if only a generic one, detect this so that I don't save anything?
This is abbreviated code I am currently using:
//grab image currently being displayed
UIImage *image = self.imageView.image;
//assign name for pic
NSString *picname = #"newpic.png";
//***I would like to do following only if the user has chosen a pic, not if it is a generic pic showing.
//save name of pic in contact entity
[self.contact setValue:picname forKey:#"pic"];
//use separate saveImageasPicName method to save the image
[self saveImage:image asPicName:picname];
//****
//save managed object context which puts name of pic in core data
if ([self.managedObjectContext save:&error]) {
//saved
}
You can declare property
#property (nonatomic, assign) BOOL imageWasPicked;
on your viewDidload set it to NO
self.imageWasPicked = NO;
After you picked the image, set flag to YES
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// image processing code
self.imageWasPicked = YES;
}
and, finally, check this flag - save data or not
if (self.wasImagePicked)
{
//grab image currently being displayed
UIImage *image = self.imageView.image;
//assign name for pic
NSString *picname = #"newpic.png";
//***I would like to do following only if the user has chosen a pic, not if it is a generic pic showing.
//save name of pic in contact entity
[self.contact setValue:picname forKey:#"pic"];
//use separate saveImageasPicName method to save the image
[self saveImage:image asPicName:picname];
//****
//save managed object context which puts name of pic in core data
if ([self.managedObjectContext save:&error]) {
//saved
}
}
Hope this helps

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"];

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);

UITableViewCell image load from url

I have a problem with loading an image from an url to display in a table. I currently have the following code to handle the image loading in a class that extends UITableViewCell:
- (void) initWithData:(NSDictionary *) data{
NSDictionary *images = [data objectForKey:#"images"];
__block NSString *poster = [images objectForKey:#"poster"];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSURL *posterURL = [[NSURL alloc] initWithString:poster];
NSData *imageData = [NSData dataWithContentsOfURL:posterURL];
if (imageData != nil) {
dispatch_async(dispatch_get_main_queue(), ^{
// 4. Set image in cell
self.backgroundImage.image = [UIImage imageWithData:imageData];
[self setNeedsLayout];
});
}
});
self.backgroundImage.image = [UIImage imageNamed:#"static"];
}
The initWithData method is called from the ViewController in the tableView:cellForRowAtIndexPath: delegate. Everything works as expected until i scroll. From what i read, the TableView cells are recycled and because the images are being loaded async, i get rows with wrong images. Also, the images are not cached and are loaded again whenever the cell is displayed.
Eg: Scroll to the middle and immediately scroll back up. The first cell will have the image that's corresponding to the middle cell that didn't get to finish loading.
Any help or suggestions? Thank you very much :)
First of all as the comment mentioned, I would definitely recommend using an existing framework/component to do this job.
The best candidates are probably:
https://github.com/rs/SDWebImage
https://github.com/enormego/EGOImageLoading
OR if you also want a general networking library
https://github.com/AFNetworking/AFNetworking
That said, if you still want to try it on your own, you would probably want to implement caching with an NSMutableDictionary using the indexPath as the key, and the image as the value.
Assuming you have an initialized instance variable NSMutableDictionary *imageCache
In your cellForRowAtIndexPath method, before attempting to do any image loading, you would check to see if your cache already has an image for this index by doing something like this
if(! imageCache[indexPath])
{
// do your web loading here, then once complete you do
imageCache[indexPath] = // the new loaded image
}
else
{
self.backgroundImage.image = imageCache[indexPath];
}

Resources