บันทึกรูปภาพลงในโฟลเดอร์เอกสารแอปพลิเคชันจาก UIView บน IOS


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 ของฉันได้ดี แต่ฉันไม่รู้ว่าจะบันทึกอย่างไร ฉันกำลังบันทึกส่วนอื่น ๆ ของมุมมอง (ส่วนใหญ่เป็น UITextfield) ใน Core Data ฉันได้ค้นหาและค้นหาและลองใช้รหัสหลายบิตที่มีคนแนะนำ แต่ฉันป้อนรหัสไม่ถูกต้องหรือคำแนะนำเหล่านั้นใช้ไม่ได้กับวิธีที่ฉันตั้งค่ารหัส มันน่าจะเป็นอดีต ฉันต้องการบันทึกภาพใน UIImageView โดยใช้การกระทำเดียวกัน (ปุ่มบันทึก) ฉันใช้บันทึกข้อความใน UITextFields นี่คือวิธีการบันทึกข้อมูล 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

นี่คือคำตอบของ Fangming Ning สำหรับ Swift 4.2ซึ่งอัปเดตด้วยวิธีการที่แนะนำและ 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.