UIImageView - How to get the file name of the image assigned?
Asked Answered
D

17

87

Is it possible to read the name of an UIImageView's UIImage that's presently stored in the UIImageView?

I was hoping you could do something kind of like this, but haven't figured it out.

NSString *currentImageName = [MyIImageView getFileName];
Dignify answered 16/11, 2009 at 5:36 Comment(1)
visit #47246887Elviaelvie
G
90

Nope. You can't do that.

The reason is that a UIImageView instance does not store an image file. It stores a displays a UIImage instance. When you make an image from a file, you do something like this:

UIImage *picture = [UIImage imageNamed:@"myFile.png"];

Once this is done, there is no longer any reference to the filename. The UIImage instance contains the data, regardless of where it got it. Thus, the UIImageView couldn't possibly know the filename.

Also, even if you could, you would never get filename info from a view. That breaks MVC.

Gawk answered 16/11, 2009 at 5:39 Comment(6)
Just because it breaks MVC doesn't mean you shouldn't do it. Rules are meant to be broken, after all ;)Highlands
Some rules are. But on iPhone and Mac, you should always do your best to adhere to MVC. They are opinionated environments.Gawk
It is actually possible to do this, but it requires screwing with the Objective-C runtime to edit imageNamed: (yes, breaking lots of rules.) If you really must do this in your project for some important reason, see my answer below.Outsail
@JonathanSterling there are many different interpretations of MVCGrapevine
It looks like UIImage(named: String) in SwiftAubry
was setAccessibilityIdentifier as suggested by nizar ahmed's answer below not available in 2009, or is there a reason not to use setAccessibilityIdentifier?Saidel
U
111

you can use setAccessibilityIdentifier method for any subclass of UIView

UIImageView *image ;
[image setAccessibilityIdentifier:@"file name"] ;

NSString *file_name = [image accessibilityIdentifier] ;
Unmannerly answered 4/9, 2012 at 11:19 Comment(4)
i came across here simply b/c i'm creating an app that has localized images.. and i want to create a localize method that simply goes through the images and does some regex on the image name (i got very good reasons to make those images actual images rather than creating a custom made UIImage).. i was wondering if there was a better cleaner way of localizing images in objective-c.. since everybody is talking about MVC and what notGrapevine
I know there is no ok with MVC, but I needed it in purpose of testing.Burble
For OSX use accessibilityDescriptionCharitacharitable
is there a technical drawback to this solution? this seems like the simplest, cleanest solution so why isn't it considered the accepted answer?Saidel
G
90

Nope. You can't do that.

The reason is that a UIImageView instance does not store an image file. It stores a displays a UIImage instance. When you make an image from a file, you do something like this:

UIImage *picture = [UIImage imageNamed:@"myFile.png"];

Once this is done, there is no longer any reference to the filename. The UIImage instance contains the data, regardless of where it got it. Thus, the UIImageView couldn't possibly know the filename.

Also, even if you could, you would never get filename info from a view. That breaks MVC.

Gawk answered 16/11, 2009 at 5:39 Comment(6)
Just because it breaks MVC doesn't mean you shouldn't do it. Rules are meant to be broken, after all ;)Highlands
Some rules are. But on iPhone and Mac, you should always do your best to adhere to MVC. They are opinionated environments.Gawk
It is actually possible to do this, but it requires screwing with the Objective-C runtime to edit imageNamed: (yes, breaking lots of rules.) If you really must do this in your project for some important reason, see my answer below.Outsail
@JonathanSterling there are many different interpretations of MVCGrapevine
It looks like UIImage(named: String) in SwiftAubry
was setAccessibilityIdentifier as suggested by nizar ahmed's answer below not available in 2009, or is there a reason not to use setAccessibilityIdentifier?Saidel
O
21

No no no… in general these things are possible. It'll just make you feel like a dirty person. If you absolutely must, do this:

  • Create a category with your own implementation of +imageNamed:(NSString*)imageName that calls through to the existing implementation and uses the technique identified here (How do I use objc_setAssociatedObject/objc_getAssociatedObject inside an object?) to permanently associate imageName with the UIImage object that is returned.

  • Use Method Swizzling to swap the provided implementation of imageNamed: for your implementation in the method lookup table of the Objective-C runtime.

  • Access the name you associated with the UIImage instance (using objc_getAssociatedObject) anytime you want it.

I can verify that this works, with the caveat that you can't get the names of UIImage's loaded in NIBs. It appears that images loaded from NIBs are not created through any standard function calls, so it's really a mystery to me.

I'm leaving the implementation up to you. Copy-pasting code that screws with the Objective-C runtime is a very bad idea, so think carefully about your project's needs and implement this only if you must.

Outsail answered 24/12, 2012 at 6:18 Comment(3)
Why don't you just create a subclass of UIImage to override a method?Zirconia
vrwim: you need to swizzle when you want to add something to an existing behaviour. if you will use category (or inheritance), you will be able to switch some code in another, but you won't be able to do that without losing the original behaviour. in other words, if you will try to write (in inherited class): +imageNamed:(NSString*)imageName { // save file name in new property or whatever [self imageNamed:imageName]; // infinite loop [super imageNamed:imageName]; // super doesn't contain such a method }Russ
hi ben any reason to not just use setAccessibilityIdentifier as suggested by nizar ahmed?Saidel
R
11

There is no native way to do this; however, you could easily create this behavior yourself.

You can subclass UIImageView and add a new instance variable:

NSString* imageFileName;

Then you could override setImage, first setting imageFileName to the filename of the image you're setting, and then calling [super setImage:imageFileName]. Something like this:

-(void) setImage:(NSString*)fileName
{
   imageFileName = fileName;
   [super setImage:fileName];
}

Just because it can't be done natively doesn't mean it isn't possible :)

Redshank answered 22/5, 2012 at 1:26 Comment(1)
Thanks for moving this and helping keep the site clean!Feldspar
E
11
if ([imageForCheckMark.image isEqual:[UIImage imageNamed:@"crossCheckMark.png"]]||[imageForCheckMark.image isEqual:[UIImage imageNamed:@"checkMark.png"]])
{

}
Engender answered 19/2, 2013 at 11:3 Comment(5)
In if condition i have just checking the name of imagesEngender
Code-only answers aren't so useful. Please add a short text explaining what your code fragment does.Muddleheaded
if condition is matching image name in imageForCheckMark and [UIImage imageNamed:@"crossCheckMark.png"]] if true then execute some line of code otherwise different line of codeEngender
This is like telling us whether the image if hot dog or not hotdog.Desrosiers
I'm creating some unittests to check if the right images are set, for me this is useful.Martyrdom
B
10

Nope. No way to do that natively. You're going to have to subclass UIImageView, and add an imageFileName property (which you set when you set the image).

Branum answered 16/11, 2009 at 5:37 Comment(1)
hi kenny any reason to not just use setAccessibilityIdentifier as suggested by nizar ahmed?Saidel
C
8

Neither UIImageView not UIImage holds on to the filename of the image loaded.

You can either

1: (as suggested by Kenny Winker above) subclass UIImageView to have a fileName property or

2: name the image files with numbers (image1.jpg, image2.jpg etc) and tag those images with the corresponding number (tag=1 for image1.jpg, tag=2 for image2.jpg etc) or

3: Have a class level variable (eg. NSString *currentFileName) which updates whenever you update the UIImageView's image

Challis answered 17/12, 2009 at 22:27 Comment(0)
D
8

In short:

uiImageView.image?.imageAsset?.value(forKey: "assetName")

UIImage has an imageAsset property (since iOS 8.0) that references the UIImageAsset it was created from (if any).

UIImageAsset has an assetName property that has the information you want. Unfortunately it is not public, hence the need to use value(forKey: "assetName"). Use at your own risk, as it's officially out of bounds for the App Store.

Daphie answered 8/6, 2022 at 8:49 Comment(0)
S
6

Or you can use the restoration identifier, like this:

let myImageView = UIImageView()
myImageView.image = UIImage(named: "anyImage")
myImageView.restorationIdentifier = "anyImage" // Same name as image's name!

// Later, in UI Tests:
print(myImageView.restorationIdentifier!) // Prints "anyImage"

Basically in this solution you're using the restoration identifier to hold the image's name, so you can use it later anywhere. If you update the image, you must also update the restoration identifier, like this:

myImageView.restorationIdentifier = "newImageName"

I hope that helps you, good luck!

Sora answered 23/5, 2017 at 11:3 Comment(0)
W
4

This code will help you out:-

- (NSString *)getFileName:(UIImageView *)imgView{
    NSString *imgName = [imgView image].accessibilityIdentifier;
    NSLog(@"%@",imgName);
    return imgName;
}

Use this as:-

NSString *currentImageName = [self getFileName:MyIImageView];
Windproof answered 29/5, 2013 at 22:39 Comment(4)
It will return null because you have not set the accessibilityIdentifier yet. Set it like this [image setAccessibilityIdentifier:@"demoFileName.png"] ; and then call this methodAdp
Console says: error: property 'accessibilityIdentifier' not found on object of type 'UIImage *' - Xcode 8.1Kingofarms
Returns Null, do not try thisDicker
anyway it returns nullDisrelish
N
3

You can use objective c Runtime feature for associating imagename with the UImageView.

First import #import <objc/runtime.h> in your class

then implement your code as below :

NSString *filename = @"exampleImage";
UIImage *image = [UIImage imagedName:filename];
objc_setAssociatedObject(image, "imageFilename", filename, OBJC_ASSOCIATION_COPY);
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
//You can then get the image later:
NSString *filename = objc_getAssociatedObject(imageView, "imageFilename");

Hope it helps you.

Nopar answered 20/12, 2013 at 9:32 Comment(0)
K
3

Yes you can compare with the help of data like below code

UITableViewCell *cell = (UITableViewCell*)[self.view viewWithTag:indexPath.row + 100];

UIImage *secondImage = [UIImage imageNamed:@"boxhover.png"];

NSData *imgData1 = UIImagePNGRepresentation(cell.imageView.image);
NSData *imgData2 = UIImagePNGRepresentation(secondImage);

BOOL isCompare =  [imgData1 isEqual:imgData2];
if(isCompare)
{
    //contain same image
    cell.imageView.image = [UIImage imageNamed:@"box.png"];
}
else
{
    //does not contain same image
    cell.imageView.image = secondImage;
}
Kellykellyann answered 13/10, 2014 at 7:1 Comment(0)
F
3

Swift 3

First set the accessibilityIdentifier as imageName

myImageView.image?.accessibilityIdentifier = "add-image"

Then Use the following code.

extension UIImageView {
  func getFileName() -> String? {
    // First set accessibilityIdentifier of image before calling.
    let imgName = self.image?.accessibilityIdentifier
    return imgName
  }
}

Finally, The calling way of method to identify

myImageView.getFileName()
Flutterboard answered 13/4, 2017 at 10:29 Comment(0)
U
3

Get image name Swift 4.2

There is a way if you want to compare button image names that you have in assets.

@IBOutlet weak var extraShotCheckbox: UIButton!

@IBAction func extraShotCheckBoxAction(_ sender: Any) {
    extraShotCheckbox.setImage(changeCheckBoxImage(button: extraShotCheckbox), for: .normal)
}

func changeCheckBoxImage(button: UIButton) -> UIImage {
    if let imageView = button.imageView, let image = imageView.image {
        if image == UIImage(named: "checkboxGrayOn") {
            return UIImage(named: "checkbox")!
        } else {
            return UIImage(named: "checkboxGrayOn")!
        }
    }
    return UIImage()
}
Ulcerative answered 25/2, 2019 at 15:21 Comment(0)
S
0

I have deal with this problem, I have been solved it by MVC design pattern, I created Card class:

@interface Card : NSObject

@property (strong,nonatomic) UIImage* img;

@property  (strong,nonatomic) NSString* url;

@end

//then in the UIViewController in the DidLoad Method to Do :

// init Cards
Card* card10= [[Card alloc]init];
card10.url=@"image.jpg";  
card10.img = [UIImage imageNamed:[card10 url]];

// for Example

UIImageView * myImageView = [[UIImageView alloc]initWithImage:card10.img];
[self.view addSubview:myImageView];

//may you want to check the image name , so you can do this:

//for example

 NSString * str = @"image.jpg";

 if([str isEqualToString: [card10 url]]){
 // your code here
 }
Susann answered 2/6, 2013 at 18:7 Comment(0)
B
-1

use below

 UIImageView *imageView = ((UIImageView *)(barButtonItem.customView.subviews.lastObject));
 file_name = imageView.accessibilityLabel;
Brinker answered 5/12, 2013 at 1:18 Comment(0)
H
-1

The code is work in swift3 - write code inside didFinishPickingMediaWithInfo delegate method:

if let referenceUrl = info[UIImagePickerControllerReferenceURL] as? NSURL {
  ALAssetsLibrary().asset(for: referenceUrl as URL!, resultBlock: { asset in

  let fileName = asset?.defaultRepresentation().filename()
  print(fileName!)

  //do whatever with your file name            
  }, failureBlock: nil)
}
Hoofer answered 27/11, 2017 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.