IOS의 UIView에서 애플리케이션 문서 폴더에 이미지 저장


114

사용자가 저장할 수있을 때까지 이미지를 배치하고 유지할 수있는 UIImageView가 있습니다. 문제는 뷰에 배치 한 이미지를 실제로 저장하고 검색하는 방법을 알 수 없다는 것입니다.

다음과 같이 UIImageView에 이미지를 검색하고 배치했습니다.

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

선택한 이미지를 내 UIImageView에 잘 표시하지만 저장하는 방법을 모릅니다. Core Data에 뷰의 다른 모든 부분 (대부분 UITextfield)을 저장하고 있습니다. 사람들이 제안한 많은 코드를 검색 및 검색하고 시도했지만 코드를 올바르게 입력하지 않았거나 해당 제안이 내 코드 설정 방식으로 작동하지 않습니다. 전자 일 가능성이 높습니다. UITextFields에 텍스트를 저장하는 데 사용하는 것과 동일한 작업 (저장 버튼)을 사용하여 UIImageView에 이미지를 저장하고 싶습니다. 내 UITextField 정보를 저장하는 방법은 다음과 같습니다.

// Handle Save Button
- (void)save {

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

앞서 말했듯이이 작업을 수행하기 위해 여러 가지 방법을 시도했지만 파악할 수 없습니다. 내 생애 처음으로 무생물에 신체적 손상을 입히고 싶었지만 스스로 제지 할 수있었습니다.

사용자가 응용 프로그램의 문서 폴더에있는 UIImageView에 배치 한 이미지를 저장 한 다음 사용자가 해당 뷰를 스택에 푸시 할 때 표시 할 다른 UIImageView에 배치 할 수 있기를 바랍니다. 어떤 도움이라도 대단히 감사합니다!

답변:


341

다 좋아, 친구. 자신이나 다른 사람을 해치지 마십시오.

데이터 세트가 너무 커지면 성능에 영향을 미칠 수 있으므로 이러한 이미지를 Core Data에 저장하고 싶지 않을 것입니다. 이미지를 파일에 쓰는 것이 좋습니다.

NSData *pngData = UIImagePNGRepresentation(image);

캡처 한 이미지의 PNG 데이터를 가져옵니다. 여기에서 파일에 쓸 수 있습니다.

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

나중에 읽어도 같은 방식으로 작동합니다. 위에서했던 것처럼 경로를 빌드 한 다음 :

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

여러분이하고 싶은 일은 경로 문자열을 생성하는 메서드를 만드는 것입니다. 그 코드가 어디에나 흩어져있는 것을 원하지 않기 때문입니다. 다음과 같이 보일 수 있습니다.

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

    return [documentsPath stringByAppendingPathComponent:name]; 
}

도움이 되었기를 바랍니다.


2
완전히 정확합니다. 이미지의 특성에 따라 Apple 스토리지 가이드 라인을 언급하고 싶습니다. 캐시에 저장해야합니다
Daij-Djan

나는 당신의 제안과 코드를 따랐습니다. 그러나 그것은 사진 섹션에 나타나지 않습니다. 어떻게 이런일이 일어 났습니까?
NovusMobile

@DaniloCampos Documents Directory 내에 폴더를 만든 다음 해당 폴더 안에 파일을 저장하는 방법은 무엇입니까?
Pradeep Reddy Kypa

3

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

이것은 Swift 4.2에 대한 Fangming Ning의 답변 이며 문서 디렉토리 경로를 검색하고 더 나은 문서 로 권장되고 더 Swifty 방법으로 업데이트되었습니다 . 새로운 방법에 대한 Fangming Ning에게도 감사드립니다.

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

여기에서 가능한 모든 데이터 쓰기 옵션을 확인하십시오.


이 올바른지? 여기 에있는 또 다른 질문에 대한 답변에서 fileURLWithPath와 함께하는 absoluteString것이 잘못되었음을 발견했습니다 .
dumbledad

@dumbledad 정보를 주셔서 감사합니다. 제 답변을 업데이트하고 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

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

사용 예

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

0

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
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.