Salva un'immagine nella cartella dei documenti dell'applicazione da UIView su IOS


114

Ho un UIImageView che consente a un utente di posizionare e mantenere un'immagine fino a quando non può essere salvata. Il problema è che non riesco a capire come salvare e recuperare effettivamente l'immagine che ho inserito nella vista.

Ho recuperato e inserito l'immagine in UIImageView in questo modo:

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

Visualizza perfettamente l'immagine selezionata nel mio UIImageView, ma non ho idea di come salvarla. Sto salvando tutti gli altri pezzi della vista (principalmente UITextfield) in Core Data. Ho cercato e cercato e provato molti bit di codice che le persone hanno suggerito, ma o non sto inserendo il codice correttamente o quei suggerimenti non funzionano con il modo in cui ho impostato il mio codice. Probabilmente è il primo. Vorrei salvare l'immagine in UIImageView utilizzando la stessa azione (un pulsante di salvataggio) che sto usando per salvare il testo in UITextFields. Ecco come sto salvando le mie informazioni UITextField:

// Handle Save Button
- (void)save {

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

Come ho detto prima, ho provato diversi metodi per farlo funzionare, ma non riesco a capirlo. Per la prima volta nella mia vita ho voluto causare danni fisici a un oggetto inanimato, ma sono riuscito a trattenermi.

Mi piacerebbe essere in grado di salvare l'immagine che l'utente inserisce in UIImageView nella cartella dei documenti dell'applicazione, quindi essere in grado di recuperarla e posizionarla in un altro UIImageView per la visualizzazione quando l'utente inserisce quella vista nello stack. Qualsiasi aiuto è molto apprezzato!

Risposte:


341

Va tutto bene, amico. Non danneggiare te stesso o gli altri.

Probabilmente non vuoi archiviare queste immagini in Core Data, poiché ciò può influire sulle prestazioni se il set di dati diventa troppo grande. Meglio scrivere le immagini su file.

NSData *pngData = UIImagePNGRepresentation(image);

Questo estrae i dati PNG dell'immagine che hai catturato. Da qui puoi scriverlo su un file:

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

Leggerlo in seguito funziona allo stesso modo. Costruisci il percorso come abbiamo appena fatto sopra, quindi:

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

Quello che probabilmente vorrai fare è creare un metodo che crei stringhe di percorso per te, dal momento che non vuoi che il codice sia disseminato ovunque. Potrebbe assomigliare a questo:

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

    return [documentsPath stringByAppendingPathComponent:name]; 
}

Spero sia utile.


2
totalmente corretto - voglio solo menzionare le linee guida per l'archiviazione di Apple quindi A SECONDA della natura delle immagini, dovrebbe essere memorizzato nella cache
Daij-Djan

Ho seguito il tuo suggerimento e codice. ma non compare nelle sezioni delle foto. Come è successo?
NovusMobile

@DaniloCampos Come creare una cartella all'interno di Documents Directory e quindi salvare il file all'interno di quella cartella?
Pradeep Reddy Kypa

3

Versione Swift 3.0

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

2

Questa è la risposta di Fangming Ning per Swift 4.2 , aggiornata con un metodo consigliato e più Swifty per il recupero del percorso della directory dei documenti e con una migliore documentazione. Si ringrazia anche Fangming Ning per il nuovo metodo.

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

Controlla tutte le possibili opzioni di scrittura dei dati qui.


È corretto? In una risposta a un'altra domanda qui ho scoperto che fileURLWithPathinsieme a absoluteStringè sbagliato.
Dumbledad

@dumbledad Grazie per le informazioni, ho aggiornato la mia risposta e ho riscritto anche il codice per Swift 4.2.
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;
}

1

Swift 4 con estensione

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

Esempio di utilizzo

 image.saveImage(inDir: .documentDirectory, name: "pic")

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
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.