Getting string value from nssarray - ios

I define an array in the 'interface' section of the view controller thus:
#property (strong, nonatomic) NSArray *images;
I load it in viewDidLoad:
self.images = #[[UIImage imageNamed:#"sophia1_1x"],
[UIImage imageNamed:#"sophia2_1x"],
[UIImage imageNamed:#"sophia3_1x"],
[UIImage imageNamed:#"sophia4_1x"],
[UIImage imageNamed:#"sophia5_1x"],
[UIImage imageNamed:#"sophia6_1x"]];
Then I want to set the image in a UIImage from the array. I can hard code the name of the image, and it works fine:
self.currentImage.image = [UIImage imageNamed:#"sophia4_1x.png"];
But if I try to get the value from the array:
self.currentImage.image = [UIImage imageNamed:self.images[row]];
I get "unrecognized selector sent to instance"
and I just...don't........understand!

Your array contains UIImage objects, not strings, so you can't pass self.images[row] to the imageNamed: method. To get an image, you just need to access the row you want in the array,
self.currentImage.image = self.images[row];

Did you mean to save an array of strings, and then use a string to load an image?
If so, your code would look like this:
#property (strong, nonatomic) NSArray *imageNames;
And the code to load it:
self.imageNames = #[
#"sophia2_1x",
#"sophia3_1x",
#"sophia4_1x",
#"sophia5_1x",
#"sophia6_1x"
];
Then your code to load an image would work:
self.currentImage.image = [UIImage imageNamed:self.imageNames[row]];
If you really wanted an array of images then relmar's solution would give you that.

Related

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

NSInvalidArgumentException exception when adding image to imageView iOS

.H files
#property (strong, nonatomic) LAClaimReport *claimReport;
.M file
#interface LACreateReportViewController ()
{
NSArray *_thumbnails;
LAPhotoThumb *_lastSelectedPhoto;
}
_thumbnails = _claimReport.photos.allObjects;
if (_thumbnails.count >0)
{
_photosCaption.textColor = [UIColor colorWithRed:0/255.0 green:46/255.0 blue:91/255.0 alpha:1];
UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(30, 1838, 300, 600)];
NSLog(#"image:%#" , _thumbnails[0]);
[image setImage:(UIImage *) _thumbnails[0]]; // exception here.
}
NSInvalidArgumentException', reason: '-[LAPhoto size]: unrecognized selector sent to instance 0xa76b720'
Photos is a column in the class file of LAClaimReport. What am i missing in regards to size here? pls guide.
_thumbnails doesn't contain UIImage instances, it contains some other type of object. Enough information isn't included to tell what kind of objects it contains however.
size is a method on UIImage that is used by the image view to determine how to display the image, and whatever object is actually in _thumbnails doesn't implement that method.
Your NSLog(#"image:%#" , _thumbnails[0]); should list the class type that you're trying to use as an image.
make sure that you have UIImage class objects in _thumbnails Array, I Think you have LAPhoto type objects in that array
id arrContent=_thumbnails[0];
if ([arrContent isKindOfClass:[LAPhoto Class]])
{
//read LAPhoto class and find a way to get the UIImage from LAPhoto Object
}
else if ([arrContent isKindOfClass:[UIImage class]])
{
[image setImage:(UIImage *) _thumbnails[0]];
}

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

How to create a UIImage property that can be accessed from any method?

I'm trying to learn objective-c and app design for Xcode through books and example, but can't seem to understand how to create a global property for a UIImage, set an image to that property, and then access that UIImage in a different method.
In my FirstViewController.m file, I added the following lines:
#interface FirstViewController ()
#property (strong, nonatomic) UIImage *workingImage;
#end
#implementation FirstViewController
- (IBAction)myMethod1:(id)sender {
... bunch of code ...
UIImage *workingImage = [info objectForKey:UIImagePickerControllerOriginalImage];
}
- (IBAction)button press:(id)sender {
CGContextRef ctx;
CGImageRef imageRef = [self.workingImage CGImage];
...bunch of code...
}
So basically I am trying to create an image variable called workingImage that I set in my method to be an actual image, and then which gets used by CGImageRef after the user pressed the button. However I don't think I have things setup correctly, because imageRef never gets set to my image.
Can someone please show me what I'm doing wrong? (And FYI, this is a code snippet from a very simple app in which the user takes a photo and then I edit it's pixels)
Here you're assigning the image to a local variable:
UIImage *workingImage = [info objectForKey:UIImagePickerControllerOriginalImage];
when what you want is to set the image to the property:
self.workingImage = [info objectForKey:UIImagePickerControllerOriginalImage];

How to get a UIImage's image as an NSString?

I need to get the value of a UIImage's image as a string.
Previously I was doing:
if(images[imageNo].image == [UIImage imageNamed:#"image1.png"])
{
But now I have a lot more conditions so I would like to use a switch, doing:
switch(images[imageNo].image)
{
case #"image1.png":
break;
}
Is there a way to achieve this? Thanks!
Mmm I am not sure what you want to accomplish here but using [UIImage imageNamed:#"image1.png"], is definitely a very bad way to do the comparison as you are creating a new UIImage object on the fly for no reason at all, furthermore you are using the == operator when you should be using isEqual since they are objects.
I believe what you want to do is convert it to a base 64 string perhaps?. If so you an use this:
NSData *imageData = UIImageJPEGRepresentation(myImage, 1.0);
NSString *encodedString = [imageData base64Encoding];
The answer provided by H2C03 is appropriate. Use a dictionary to associate the names.
However, an alternative is using associative objects. Note that there is a cost in both space and time using associative objects, but they are convenient for just this type of case (adding a category-property).
#interface UIImage (MyImageLabel)
#property (nonatomic, copy) NSString *label;
#end
#import <objc/runtime.h>
#implementation UIImage (MyImageLabel)
static char const kImageLabelKey[1];
- (NSString*)label {
return objc_getAssociatedObject(self, kImageLabelKey);
}
- (void)setLabel:(NSString *)label {
objc_setAssociatedObject(self, kImageLabelKey, label, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
#end
Now, you can have a label property on your UIImage instances, like so:
myImage.label = someLabelStringCouldEvenBeFilename;
and
if ([myImage.label isEqualToString:someString]) {
}
The typical caveats apply regarding anything in a category. Most will encourage you to use a unique prefix or postfix to differentiate your category methods from potential future Apple names.
Note, that you could add another method to the category, like this...
+ (UIImage)myImageNamed:(NSString*)name {
id result = [self imageNamed:name];
[result setLabel:name];
return result;
}
and now you automatically set the label.
Of course, you could do this as a subclass, if you will always be creating your own image, and avoid the "nastiness" associated with associative objects (though all your images need to be MyUIImages).
#interface MyUIImage : UIImage
#property (nonatomic, copy) NSString *label;
#end
#implementation MyUIImage
// Now, you override imageNamed:
+ (UIImage*)imageNamed:(NSString*)name {
UIImage *image = [super imageNamed:name];
self.label = name;
return image;
}
#end
Both of your approaches are incorrect. The first one relies on caching (which is not documented), meanwhile the second is a syntax error - the 'case' keywords expect a compile-time constant expression.
As far as I know, there's no such a method in the iOS SDK that would return an image's filename - simply because it's not a property of the image (what would it return for a programmatically created image?). You should instead try to operate on an NSDictionary, storing the UIImage objects associated with the filenames as keys, and comparing the keys using isEqualToString:.
So you should create your images only once, and store them in a dictionary:
// assuming `images` is an already created instance variable of your class
[images setObject:[UIImage imageNamed:#"ImgOne.png"] forKey:#"ImgOne.png"];
// and so on, with every image you need
// then once you have to check against a file name, use:
UIImage *img = [images objectForKey:#"FileName.png"];
if ([someImage isEqual:img]) {
// you can now be sure that the image set to the object was once named "FileName"
}

Resources