UIImageView - ¿Cómo obtener el nombre de archivo de la imagen asignada?

82

¿Es posible leer el nombre de un UIImageView's UIImage que está almacenado actualmente en el UIImageView?

Esperaba que pudieras hacer algo como esto, pero no lo he descubierto.

NSString *currentImageName = [MyIImageView getFileName];
Kuberchaun
fuente

Respuestas:

88

No No puedes hacer eso.

La razón es que una UIImageViewinstancia no almacena un archivo de imagen. Almacena una muestra una UIImageinstancia. Cuando crea una imagen a partir de un archivo, hace algo como esto:

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

Una vez hecho esto, ya no hay ninguna referencia al nombre del archivo. La UIImageinstancia contiene los datos, independientemente de dónde los haya obtenido. Por tanto, UIImageViewno es posible que sepa el nombre del archivo.

Además, incluso si pudiera, nunca obtendría la información del nombre de archivo de una vista. Eso rompe MVC.

Jonathan Sterling
fuente
62
El hecho de que rompa MVC no significa que no deba hacerlo. Las reglas están destinadas a romperse, después de todo;)
Sneakyness
10
Algunas reglas lo son. Pero en iPhone y Mac, siempre debe hacer todo lo posible para cumplir con MVC. Son entornos obstinados.
Jonathan Sterling
En realidad, es posible hacer esto, pero requiere jugar con el tiempo de ejecución de Objective-C para editar imageNamed: (sí, rompiendo muchas reglas). Si realmente debe hacer esto en su proyecto por alguna razón importante, vea mi respuesta a continuación.
Ben Gotow
3
@JonathanSterling hay muchas interpretaciones diferentes de MVC
abbood
Parece UIImage (llamado: String) en Swift
RedEagle2000
109

puede usar el método setAccessibilityIdentifier para cualquier subclase de UIView

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

NSString *file_name = [image accessibilityIdentifier] ;
Nizar Ahmed
fuente
1
me encontré aquí simplemente porque estoy creando una aplicación que tiene imágenes localizadas ... y quiero crear un localizemétodo que simplemente pase por las imágenes y haga algunas expresiones regulares en el nombre de la imagen (tengo muy buenas razones para hacer esas imágenes imágenes reales en lugar de crear un UIImage personalizado) ... me preguntaba si había una forma mejor y más limpia de localizar imágenes en objetivo-c ... ya que todo el mundo está hablando de MVC y lo que no
abbood
1
Sé que MVC no está bien, pero lo necesitaba para probarlo.
Radek Wilczak
Para uso de OSXaccessibilityDescription
Anoop Vaidya
¿Existe algún inconveniente técnico en esta solución? esta parece la solución más simple y limpia, entonces, ¿por qué no se considera la respuesta aceptada?
Crashalot
19

No no no… en general estas cosas son posibles. Simplemente te hará sentir como una persona sucia. Si es absolutamente necesario, haga esto:

  • Cree una categoría con su propia implementación +imageNamed:(NSString*)imageNameque llame a la implementación existente y utilice la técnica identificada aquí ( ¿Cómo uso objc_setAssociatedObject / objc_getAssociatedObject dentro de un objeto? ) Para asociar permanentemente imageNamecon el objeto UIImage que se devuelve.

  • Utilice Method Swizzling para intercambiar la implementación proporcionada de imageNamed:para su implementación en la tabla de búsqueda de métodos del tiempo de ejecución de Objective-C.

  • Acceda al nombre que asoció con la instancia de UIImage (usando objc_getAssociatedObject) cuando lo desee.

Puedo verificar que esto funciona, con la salvedad de que no se pueden cargar los nombres de UIImage en los NIB. Parece que las imágenes cargadas desde NIB no se crean a través de llamadas de función estándar, por lo que es realmente un misterio para mí.

Dejo la implementación en tus manos. Copiar y pegar código que se enrede con el tiempo de ejecución de Objective-C es una muy mala idea, así que piense detenidamente en las necesidades de su proyecto e impleméntelo solo si es necesario.

Ben Gotow
fuente
1
¿Por qué no crea una subclase de UIImagepara anular un método?
vrwim
vrwim: debe utilizar swizzle cuando desee agregar algo a un comportamiento existente. si usa la categoría (o herencia), podrá cambiar un código en otro, pero no podrá hacerlo sin perder el comportamiento original. en otras palabras, si intenta escribir (en la clase heredada): +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 }
yonivav
Hola, ¿hay alguna razón para no usar setAccessibilityIdentifier como lo sugiere nizar ahmed?
Crashalot
10

No existe una forma nativa de hacer esto; sin embargo, usted mismo podría crear fácilmente este comportamiento.

Puede crear UIImageViewuna subclase y agregar una nueva variable de instancia:

NSString* imageFileName;

Luego puede anular setImage, primero configurando imageFileNameel nombre de archivo de la imagen que está configurando y luego llamando [super setImage:imageFileName]. Algo como esto:

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

El hecho de que no se pueda hacer de forma nativa no significa que no sea posible :)

WendiKidd
fuente
¡Gracias por mover esto y ayudar a mantener limpio el sitio!
jscs
10
if ([imageForCheckMark.image isEqual:[UIImage imageNamed:@"crossCheckMark.png"]]||[imageForCheckMark.image isEqual:[UIImage imageNamed:@"checkMark.png"]])
{

}
iEinstein
fuente
En condición if, acabo de comprobar el nombre de las imágenes
iEinstein
2
Las respuestas de solo código no son tan útiles. Agregue un texto breve que explique qué hace su fragmento de código.
nalply
si la condición coincide con el nombre de la imagen en imageForCheckMark y [UIImage imageNamed: @ "crossCheckMark.png"]] si es verdadera, entonces ejecute alguna línea de código, de lo contrario, una línea de código diferente
iEinstein
Esto es como decirnos si la imagen si hot dogo not hotdog.
ScottyBlades
Estoy creando algunas pruebas unitarias para comprobar si se han configurado las imágenes correctas, para mí esto es útil.
MQoder
9

No No hay forma de hacerlo de forma nativa. Tendrá que crear una subclase de UIImageView y agregar una propiedad imageFileName (que establece cuando establece la imagen).

Kenny Winker
fuente
hola kenny ¿alguna razón para no usar setAccessibilityIdentifier como lo sugiere nizar ahmed?
Crashalot
7

Ni UIImageView ni UIImage se aferran al nombre de archivo de la imagen cargada.

Tu también puedes

1: (como sugirió Kenny Winker arriba) subclase UIImageView para tener una propiedad fileName o

2: nombre los archivos de imagen con números (imagen1.jpg, imagen2.jpg, etc.) y etiquete esas imágenes con el número correspondiente (etiqueta = 1 para imagen1.jpg, etiqueta = 2 para imagen2.jpg, etc.) o

3: Tenga una variable de nivel de clase (por ejemplo, NSString * currentFileName) que se actualice cada vez que actualice la imagen de UIImageView

Mihir Mathuria
fuente
3

Este código te ayudará a: -

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

Utilice esto como: -

NSString *currentImageName = [self getFileName:MyIImageView];
junaidsidhu
fuente
Devolverá nulo porque aún no ha configurado el accessibilityIdentifier. [image setAccessibilityIdentifier:@"demoFileName.png"] ;
Configúrelo
La consola dice: error: la propiedad 'accessibilityIdentifier' no se encuentra en el objeto de tipo 'UIImage *' - Xcode 8.1
Jamal Zafar
Devuelve nulo, no intente esto
Kingsley Mitchell
de todos modos devuelve nulo
Saranjith
3

O puede usar el identificador de restauración, así:

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"

Básicamente, en esta solución, está utilizando el identificador de restauración para mantener el nombre de la imagen, por lo que puede usarlo más tarde en cualquier lugar. Si actualiza la imagen, también debe actualizar el identificador de restauración, así:

myImageView.restorationIdentifier = "newImageName"

Espero que te ayude, ¡buena suerte!

ThiagoAM
fuente
2

Sí, puede comparar con la ayuda de datos como el siguiente código

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;
}
Hardik Mamtora
fuente
2

Puede utilizar la función Object C Runtime para asociar el nombre de la imagen con UImageView.

Primera importación #import <objc/runtime.h>en su clase

luego implemente su código de la siguiente manera:

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

Espero que te ayude.

Nishant Tyagi
fuente
2

Obtener el nombre de la imagen Swift 4.2

Existe una forma si desea comparar los nombres de las imágenes de los botones que tiene en los activos.

@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()
}
Doci
fuente
1

Swift 3

Primero establezca el accessibilityIdentifier como imageName

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

Luego use el siguiente código.

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

Finalmente, la forma de llamada del método para identificar

myImageView.getFileName()
Abdul Hameed
fuente
0

Me he ocupado de este problema, lo resolvió el patrón de diseño MVC, creé la clase de tarjeta:

@interface Card : NSObject

@property (strong,nonatomic) UIImage* img;

@property  (strong,nonatomic) NSString* url;

@end

// luego en UIViewControllerel DidLoadMétodo a hacer:

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

// por ejemplo

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

// tal vez quieras comprobar el nombre de la imagen, para que puedas hacer esto:

//por ejemplo

 NSString * str = @"image.jpg";

 if([str isEqualToString: [card10 url]]){
 // your code here
 }
Hasan Sawaed
fuente
-1

utilizar a continuación

 UIImageView *imageView = ((UIImageView *)(barButtonItem.customView.subviews.lastObject));
 file_name = imageView.accessibilityLabel;
ramo
fuente
-1

El código funciona en swift3: escriba el código dentro del método delegado didFinishPickingMediaWithInfo:

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)
}
Niraj Paul
fuente