Salvar uma imagem na pasta de documentos do aplicativo de UIView no IOS


114

Eu tenho um UIImageView que permite ao usuário colocar e segurar uma imagem até que ela possa ser salva. O problema é que não consigo descobrir como salvar e recuperar a imagem que coloquei na visualização.

Eu recuperei e coloquei a imagem no UIImageView assim:

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

Ele exibe a imagem selecionada em meu UIImageView muito bem, mas não tenho ideia de como salvá-la. Estou salvando todas as outras partes da visualização (principalmente UITextfield) no Core Data. Eu pesquisei e pesquisei e tentei muitos bits de código que as pessoas sugeriram, mas ou não estou inserindo o código corretamente, ou essas sugestões não funcionam da maneira como eu tenho meu código configurado. Provavelmente é o primeiro. Gostaria de salvar a imagem no UIImageView usando a mesma ação (um botão salvar) que estou usando para salvar o texto no UITextFields. É assim que estou salvando minhas informações UITextField:

// Handle Save Button
- (void)save {

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

Como eu disse antes, tentei vários métodos para fazer isso funcionar, mas não consigo entender. Pela primeira vez na vida, quis causar dano físico a um objeto inanimado, mas consegui me conter.

Eu gostaria de poder salvar a imagem que o usuário coloca no UIImageView na pasta de documentos do aplicativo e, em seguida, poder recuperá-la e colocá-la em outro UIImageView para exibição quando o usuário colocar essa visualização na pilha. Qualquer ajuda é muito apreciada!

Respostas:


341

Está tudo bem, cara. Não prejudique a si mesmo ou aos outros.

Você provavelmente não deseja armazenar essas imagens no Core Data, pois isso pode afetar o desempenho se o conjunto de dados ficar muito grande. Melhor gravar as imagens em arquivos.

NSData *pngData = UIImagePNGRepresentation(image);

Isso puxa os dados PNG da imagem que você capturou. A partir daqui, você pode gravá-lo em um arquivo:

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

Ler mais tarde funciona da mesma maneira. Construa o caminho como acabamos de fazer acima e:

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

O que você provavelmente vai querer fazer é criar um método que crie strings de caminho para você, já que você não quer esse código espalhado por toda parte. Pode ser assim:

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

    return [documentsPath stringByAppendingPathComponent:name]; 
}

Espero que isso seja útil.


2
totalmente correto - só quero mencionar as Diretrizes de armazenamento da Apple, portanto, DEPENDENDO da natureza das imagens, elas devem ser armazenadas em Caches
Daij-Djan

Segui sua sugestão e código. mas não está aparecendo nas seções de fotos. Como isso aconteceu?
NovusMobile

@DaniloCampos Como criar uma pasta dentro do Diretório de Documentos e depois salvar o arquivo dentro dessa pasta?
Pradeep Reddy Kypa

3

Versão 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

Esta é a resposta do Fangming Ning para o Swift 4.2 , atualizado com um método recomendado e mais Swifty para recuperar o caminho do diretório do documento e com melhor documentação. Créditos para Fangming Ning pelo novo método também.

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

Confira todas as opções de gravação de dados possíveis aqui.


Isso está correto? Em uma resposta a outra pergunta aqui eu descobri que fileURLWithPathjunto com absoluteStringestá errado.
dumbledad

@dumbledad Obrigado pela informação, eu atualizei minha resposta e reescrevi o código para Swift 4.2 também.
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 com extensão

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

Exemplo de uso

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

0

Em 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
    }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.