UIImageView - Wie erhalte ich den Dateinamen des zugewiesenen Bildes?

82

Ist es möglich, den Namen eines zu lesen UIImageView's UIImage , der derzeit in der gespeichert ist UIImageView?

Ich hatte gehofft, Sie könnten so etwas tun, habe es aber nicht herausgefunden.

NSString *currentImageName = [MyIImageView getFileName];
Kuberchaun
quelle

Antworten:

88

Nee. Das kannst du nicht machen.

Der Grund ist, dass eine UIImageViewInstanz keine Bilddatei speichert. Es speichert eine Anzeige einer UIImageInstanz. Wenn Sie ein Bild aus einer Datei erstellen, gehen Sie folgendermaßen vor:

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

Sobald dies erledigt ist, gibt es keinen Verweis mehr auf den Dateinamen. Die UIImageInstanz enthält die Daten, unabhängig davon, woher sie stammen. Somit konnte der UIImageViewden Dateinamen unmöglich kennen.

Selbst wenn Sie könnten, würden Sie niemals Dateinameninformationen aus einer Ansicht erhalten. Das bricht MVC.

Jonathan Sterling
quelle
62
Nur weil es MVC kaputt macht, heißt das nicht, dass Sie es nicht tun sollten. Regeln sollen doch gebrochen werden;)
Sneakyness
10
Einige Regeln sind. Auf iPhone und Mac sollten Sie jedoch immer Ihr Bestes geben, um MVC einzuhalten. Sie sind einfühlsame Umgebungen.
Jonathan Sterling
Es ist tatsächlich möglich, dies zu tun, aber es erfordert das Verschrauben mit der Objective-C-Laufzeit, um imageNamed zu bearbeiten: (Ja, viele Regeln brechen .) Wenn Sie dies aus einem wichtigen Grund wirklich in Ihrem Projekt tun müssen , lesen Sie meine Antwort unten.
Ben Gotow
3
@ JonathanSterling gibt es viele verschiedene Interpretationen von MVC
Abbood
Es sieht aus wie UIImage (benannt: String) in Swift
RedEagle2000
109

Sie können die setAccessibilityIdentifier-Methode für jede Unterklasse von UIView verwenden

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

NSString *file_name = [image accessibilityIdentifier] ;
Nizar Ahmed
quelle
1
Ich bin hier einfach r / c rübergekommen. Ich erstelle eine App, die Bilder lokalisiert hat. Und ich möchte eine localizeMethode erstellen , die einfach die Bilder durchgeht und einen regulären Ausdruck für den Bildnamen macht (ich habe sehr gute Gründe, diese zu erstellen Bilder tatsächliche Bilder anstatt ein maßgeschneidertes UIImage zu erstellen) .. Ich habe mich gefragt, ob es eine bessere sauberere Möglichkeit gibt, Bilder in Objective-C zu lokalisieren .. da alle über MVC sprechen und was nicht
Abbood
1
Ich weiß, dass MVC nicht in Ordnung ist, aber ich brauchte es zum Testen.
Radek Wilczak
Für OSX verwendenaccessibilityDescription
Anoop Vaidya
Gibt es einen technischen Nachteil dieser Lösung? Dies scheint die einfachste und sauberste Lösung zu sein. Warum wird sie nicht als akzeptierte Antwort angesehen?
Crashalot
19

Nein, nein, nein ... im Allgemeinen sind diese Dinge möglich. Sie fühlen sich einfach wie eine schmutzige Person. Wenn Sie unbedingt müssen, tun Sie dies:

  • Erstellen Sie eine Kategorie mit Ihrer eigenen Implementierung +imageNamed:(NSString*)imageName, die die vorhandene Implementierung aufruft, und verwenden Sie die hier angegebene Technik ( Wie verwende ich objc_setAssociatedObject / objc_getAssociatedObject in einem Objekt? ), Um eine dauerhafte Verknüpfung imageNamemit dem zurückgegebenen UIImage-Objekt herzustellen.

  • Verwenden Sie Method Swizzling , um die bereitgestellte Implementierung von imageNamed:für Ihre Implementierung in der Methoden-Nachschlagetabelle der Objective-C-Laufzeit auszutauschen .

  • Greifen Sie jederzeit auf den Namen zu, den Sie der UIImage-Instanz zugeordnet haben (mit objc_getAssociatedObject).

Ich kann überprüfen, ob dies funktioniert, mit der Einschränkung, dass Sie die Namen von UIImage nicht in NIBs laden können. Es scheint, dass von NIBs geladene Bilder nicht durch Standardfunktionsaufrufe erstellt werden, daher ist es mir wirklich ein Rätsel.

Ich überlasse die Implementierung Ihnen. Das Einfügen von Code, der mit der Objective-C-Laufzeit verschraubt ist, ist eine sehr schlechte Idee. Denken Sie also sorgfältig über die Anforderungen Ihres Projekts nach und implementieren Sie dies nur, wenn Sie dies müssen.

Ben Gotow
quelle
1
Warum erstellen Sie nicht einfach eine Unterklasse von UIImage, um eine Methode zu überschreiben?
vrwim
vrwim: Sie müssen swizzeln, wenn Sie einem vorhandenen Verhalten etwas hinzufügen möchten. Wenn Sie eine Kategorie (oder Vererbung) verwenden, können Sie einen Code in einen anderen wechseln, aber Sie können dies nicht tun, ohne das ursprüngliche Verhalten zu verlieren. Mit anderen Worten, wenn Sie versuchen zu schreiben (in +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 }
geerbter
Hallo Ben, gibt es einen Grund, nicht nur setAccessibilityIdentifier zu verwenden, wie von Nizar Ahmed vorgeschlagen?
Crashalot
10

Es gibt keine native Möglichkeit, dies zu tun. Sie können dieses Verhalten jedoch leicht selbst erstellen.

Sie können UIImageVieweine neue Instanzvariable unterordnen und hinzufügen:

NSString* imageFileName;

Dann können Sie überschreiben setImage, indem Sie zuerst imageFileNameden Dateinamen des von Ihnen eingestellten Bildes festlegen und dann aufrufen [super setImage:imageFileName]. Etwas wie das:

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

Nur weil es nicht nativ gemacht werden kann, heißt das nicht, dass es nicht möglich ist :)

WendiKidd
quelle
Vielen Dank, dass Sie dies verschoben und dazu beigetragen haben, die Website sauber zu halten!
Jscs
10
if ([imageForCheckMark.image isEqual:[UIImage imageNamed:@"crossCheckMark.png"]]||[imageForCheckMark.image isEqual:[UIImage imageNamed:@"checkMark.png"]])
{

}
iEinstein
quelle
In diesem Zustand habe ich gerade den Namen der Bilder überprüft
iEinstein
2
Nur-Code-Antworten sind nicht so nützlich. Bitte fügen Sie einen kurzen Text hinzu, der erklärt, was Ihr Codefragment tut.
Nalply
Wenn die Bedingung mit dem Bildnamen in imageForCheckMark und [UIImage imageNamed: @ "crossCheckMark.png"] übereinstimmt, wenn true, führen Sie eine Codezeile aus, ansonsten eine andere Codezeile
iEinstein
Dies ist wie zu sagen, ob das Bild wenn hot dogoder not hotdog.
ScottyBlades
Ich erstelle einige Unittests, um zu überprüfen, ob die richtigen Bilder eingestellt sind. Für mich ist dies nützlich.
MQoder
9

Nee. Keine Möglichkeit, das nativ zu tun. Sie müssen UIImageView in eine Unterklasse unterteilen und eine imageFileName-Eigenschaft hinzufügen (die Sie beim Festlegen des Bildes festgelegt haben).

Kenny Winker
quelle
Hallo Kenny, gibt es einen Grund, nicht nur setAccessibilityIdentifier zu verwenden, wie von Nizar Ahmed vorgeschlagen?
Crashalot
7

Weder UIImageView noch UIImage behalten den Dateinamen des geladenen Bildes bei.

Du kannst entweder

1: (wie von Kenny Winker oben vorgeschlagen) Unterklasse UIImageView mit einer fileName-Eigenschaft oder

2: Benennen Sie die Bilddateien mit Nummern (image1.jpg, image2.jpg usw.) und kennzeichnen Sie diese Bilder mit der entsprechenden Nummer (tag = 1 für image1.jpg, tag = 2 für image2.jpg usw.) oder

3: Haben Sie eine Variable auf Klassenebene (z. B. NSString * currentFileName), die jedes Mal aktualisiert wird, wenn Sie das Image von UIImageView aktualisieren

Mihir Mathuria
quelle
3

Dieser Code hilft Ihnen: -

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

Verwenden Sie dies als: -

NSString *currentImageName = [self getFileName:MyIImageView];
junaidsidhu
quelle
Es wird null zurückgegeben, da Sie den accessibilityIdentifier noch nicht festgelegt haben. [image setAccessibilityIdentifier:@"demoFileName.png"] ;
Stellen
Konsole sagt: Fehler: Eigenschaft 'accessibilityIdentifier' wurde nicht für Objekt vom Typ 'UIImage *' gefunden - Xcode 8.1
Jamal Zafar
Gibt Null zurück, versuchen Sie dies nicht
Kingsley Mitchell
Trotzdem
3

Oder Sie können die Wiederherstellungskennung wie folgt verwenden:

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"

Grundsätzlich verwenden Sie in dieser Lösung die Wiederherstellungskennung, um den Namen des Bildes zu speichern, damit Sie ihn später überall verwenden können. Wenn Sie das Image aktualisieren, müssen Sie auch die Wiederherstellungskennung wie folgt aktualisieren:

myImageView.restorationIdentifier = "newImageName"

Ich hoffe das hilft dir, viel Glück!

ThiagoAM
quelle
2

Ja, Sie können mit Hilfe von Daten wie dem folgenden Code vergleichen

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
quelle
2

Sie können die Ziel-c-Laufzeitfunktion verwenden, um den Bildnamen mit der UImageView zu verknüpfen.

Zuerst #import <objc/runtime.h>in Ihre Klasse importieren

Implementieren Sie dann Ihren Code wie folgt:

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

Hoffe es hilft dir.

Nishant Tyagi
quelle
2

Holen Sie sich den Bildnamen Swift 4.2

Es gibt eine Möglichkeit, wenn Sie die Namen von Schaltflächenbildern vergleichen möchten, die Sie in Assets haben.

@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
quelle
1

Swift 3

Legen Sie zuerst den accessibilityIdentifier als imageName fest

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

Verwenden Sie dann den folgenden Code.

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

Schließlich die aufrufende Methode zur Identifizierung

myImageView.getFileName()
Abdul Hameed
quelle
0

Ich habe mich mit diesem Problem befasst, ich habe es durch MVC-Entwurfsmuster gelöst, ich habe eine Kartenklasse erstellt:

@interface Card : NSObject

@property (strong,nonatomic) UIImage* img;

@property  (strong,nonatomic) NSString* url;

@end

// dann in der UIViewControllerin der DidLoadMethode zu tun:

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

// zum Beispiel

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

// Vielleicht möchten Sie den Bildnamen überprüfen, damit Sie dies tun können:

//zum Beispiel

 NSString * str = @"image.jpg";

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

unten verwenden

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

Der Code funktioniert in swift3 - schreiben Sie Code in die didFinishPickingMediaWithInfo-Delegatenmethode:

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
quelle