Speichern Sie ein Bild im Ordner "Anwendungsdokumente" von UIView On IOS

114

Ich habe eine UIImageView, mit der ein Benutzer ein Bild platzieren und halten kann, bis es gespeichert werden kann. Das Problem ist, ich kann nicht herausfinden, wie das Bild, das ich in der Ansicht platziert habe, tatsächlich gespeichert und abgerufen werden kann.

Ich habe das Bild wie folgt abgerufen und in der UIImageView platziert:

//Get Image 
- (void) getPicture:(id)sender {
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;
    picker.allowsEditing = YES;
    picker.sourceType = (sender == myPic) ? UIImagePickerControllerSourceTypeCamera : UIImagePickerControllerSourceTypeSavedPhotosAlbum;
    [self presentModalViewController:picker animated:YES];
    [picker release];
}


- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage (UIImage *)image editingInfo:(NSDictionary *)editingInfo {
    myPic.image = image;
    [picker dismissModalViewControllerAnimated:YES];
}

Das ausgewählte Bild wird in meiner UIImageView gut angezeigt, aber ich habe keine Ahnung, wie ich es speichern soll. Ich speichere alle anderen Teile der Ansicht (hauptsächlich UITextfield) in Core Data. Ich habe gesucht und gesucht und viele Code-Teile ausprobiert, die von den Leuten vorgeschlagen wurden, aber entweder gebe ich den Code nicht richtig ein oder diese Vorschläge funktionieren nicht mit der Art und Weise, wie ich meinen Code eingerichtet habe. Es ist wahrscheinlich das erstere. Ich möchte das Bild in der UIImageView mit derselben Aktion (einer Schaltfläche zum Speichern) speichern, mit der ich den Text in den UITextFields speichere. So speichere ich meine UITextField-Informationen:

// Handle Save Button
- (void)save {

    // Get Info From UI
    [self.referringObject setValue:self.myInfo.text forKey:@"myInfo"];

Wie ich bereits sagte, habe ich verschiedene Methoden ausprobiert, um dies zum Laufen zu bringen, kann es aber nicht verstehen. Zum ersten Mal in meinem Leben wollte ich einem leblosen Objekt körperlichen Schaden zufügen, aber ich habe es geschafft, mich zurückzuhalten.

Ich möchte in der Lage sein, das Bild, das der Benutzer in der UIImageView im Dokumentordner der Anwendung ablegt, zu speichern und es dann abzurufen und in einer anderen UIImageView abzulegen, um es anzuzeigen, wenn der Benutzer diese Ansicht auf den Stapel schiebt. Jede Hilfe wird sehr geschätzt!

vergessen
quelle

Antworten:

341

Es ist alles gut, Mann. Verletze dich selbst oder andere nicht.

Sie möchten diese Bilder wahrscheinlich nicht in Core Data speichern, da dies die Leistung beeinträchtigen kann, wenn der Datensatz zu groß wird. Besser die Bilder in Dateien schreiben.

NSData *pngData = UIImagePNGRepresentation(image);

Dadurch werden PNG-Daten des von Ihnen aufgenommenen Bildes abgerufen. Von hier aus können Sie es in eine Datei schreiben:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory 
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"image.png"]; //Add the file name
[pngData writeToFile:filePath atomically:YES]; //Write the file

Das spätere Lesen funktioniert genauso. Bauen Sie den Pfad wie oben beschrieben, dann:

NSData *pngData = [NSData dataWithContentsOfFile:filePath];
UIImage *image = [UIImage imageWithData:pngData];

Was Sie wahrscheinlich tun möchten, ist eine Methode zu erstellen, die Pfadzeichenfolgen für Sie erstellt, da Sie nicht möchten, dass dieser Code überall verstreut ist. Es könnte so aussehen:

- (NSString *)documentsPathForFileName:(NSString *)name
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);  
    NSString *documentsPath = [paths objectAtIndex:0];

    return [documentsPath stringByAppendingPathComponent:name]; 
}

Hoffe das ist hilfreich.

Danilo Campos
quelle
2
Völlig korrekt - ich möchte nur die Apple-Speicherrichtlinien erwähnen. Abhängig von der Art der Bilder sollte sie unter Caches gespeichert werden
Daij-Djan
Ich bin Ihrem Vorschlag und Code gefolgt. aber es erscheint nicht in den Fotobereichen. Wie ist es passiert?
NovusMobile
@DaniloCampos Wie erstelle ich einen Ordner im Dokumentenverzeichnis und speichere die Datei in diesem Ordner?
Pradeep Reddy Kypa
3

Swift 3.0 Version

let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
        
let img = UIImage(named: "1.jpg")!// Or use whatever way to get the UIImage object
let imgPath = URL(fileURLWithPath: documentDirectoryPath.appendingPathComponent("1.jpg"))// Change extension if you want to save as PNG

do{
    try UIImageJPEGRepresentation(img, 1.0)?.write(to: imgPath, options: .atomic)//Use UIImagePNGRepresentation if you want to save as PNG
}catch let error{
    print(error.localizedDescription)
}
Fangming
quelle
2

Dies ist Fangming Nings Antwort für Swift 4.2 , aktualisiert mit einer empfohlenen und schnelleren Methode zum Abrufen des Dokumentverzeichnispfads und mit einer besseren Dokumentation. Dank an Fangming Ning für die neue Methode.

guard let documentDirectoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
    return
}

//Using force unwrapping here because we're sure "1.jpg" exists. Remember, this is just an example.
let img = UIImage(named: "1.jpg")!

// Change extension if you want to save as PNG.
let imgPath = documentDirectoryPath.appendingPathComponent("1.jpg")

do {
    //Use .pngData() if you want to save as PNG.
    //.atomic is just an example here, check out other writing options as well. (see the link under this example)
    //(atomic writes data to a temporary file first and sending that file to its final destination)
    try img.jpegData(compressionQuality: 1)?.write(to: imgPath, options: .atomic)
} catch {
    print(error.localizedDescription)
}

Hier finden Sie alle möglichen Optionen zum Schreiben von Daten.

Tamás Sengel
quelle
Ist das richtig? Bei einer Antwort auf eine andere Frage hier fand ich, dass fileURLWithPathzusammen mit absoluteStringfalsch ist.
Dumbledad
@dumbledad Vielen Dank für die Informationen, ich habe meine Antwort aktualisiert und den Code für Swift 4.2 ebenfalls neu geschrieben.
Tamás Sengel
2
#pragma mark - Save Image To Local Directory

- (void)saveImageToDocumentDirectoryWithImage:(UIImage *)capturedImage {
    NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
    NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"/images"];
    
    //Create a folder inside Document Directory
    if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
        [[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]; //Create folder

    NSString *imageName = [NSString stringWithFormat:@"%@/img_%@.png", dataPath, [self getRandomNumber]] ;
    // save the file
    if ([[NSFileManager defaultManager] fileExistsAtPath:imageName]) {
        // delete if exist
        [[NSFileManager defaultManager] removeItemAtPath:imageName error:nil];
    }
    
    NSData *imageDate = [NSData dataWithData:UIImagePNGRepresentation(capturedImage)];
    [imageDate writeToFile: imageName atomically: YES];
}


#pragma mark - Generate Random Number

- (NSString *)getRandomNumber {
    NSTimeInterval time = ([[NSDate date] timeIntervalSince1970]); // returned as a double
    long digits = (long)time; // this is the first 10 digits
    int decimalDigits = (int)(fmod(time, 1) * 1000); // this will get the 3 missing digits
    //long timestamp = (digits * 1000) + decimalDigits;
    NSString *timestampString = [NSString stringWithFormat:@"%ld%d",digits ,decimalDigits];
    return timestampString;
}
Mannam Brahmam
quelle
1

Swift 4 mit Verlängerung

extension UIImage{

func saveImage(inDir:FileManager.SearchPathDirectory,name:String){
    guard let documentDirectoryPath = FileManager.default.urls(for: inDir, in: .userDomainMask).first else {
        return
    }
    let img = UIImage(named: "\(name).jpg")!

    // Change extension if you want to save as PNG.
    let imgPath = URL(fileURLWithPath: documentDirectoryPath.appendingPathComponent("\(name).jpg").absoluteString)
    do {
        try UIImageJPEGRepresentation(img, 0.5)?.write(to: imgPath, options: .atomic)
    } catch {
        print(error.localizedDescription)
    }
  }
}

Anwendungsbeispiel

 image.saveImage(inDir: .documentDirectory, name: "pic")
levin varghese
quelle
0

In Swift:

let paths: [NSString?] = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .LocalDomainMask, true)
if let path = paths[0]?.stringByAppendingPathComponent(imageName) {
    do {
        try UIImagePNGRepresentation(image)?.writeToFile(path, options: .DataWritingAtomic)
    } catch {
        return
    }
}
NatashaTheRobot
quelle