CHRIS
CHRIS

Reputation: 955

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!

Upvotes: 0

Views: 13771

Answers (3)

Jody Hagins
Jody Hagins

Reputation: 28349

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

Upvotes: 1

user529758
user529758

Reputation:

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"
}

Upvotes: 0

Oscar Gomez
Oscar Gomez

Reputation: 18488

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

Upvotes: 2

Related Questions