从 iOS 上的 UIView 将图像保存到应用程序文档文件夹
Posted
技术标签:
【中文标题】从 iOS 上的 UIView 将图像保存到应用程序文档文件夹【英文标题】:Save An Image To Application Documents Folder From UIView On IOS 【发布时间】:2011-07-25 19:51:09 【问题描述】:我有一个 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 中。我已经搜索和搜索,并尝试了人们建议的许多代码,但要么我没有正确输入代码,要么这些建议不适用于我设置代码的方式。很可能是前者。我想使用我用来将文本保存在 UITextFields 中的相同操作(保存按钮)将图像保存在 UIImageView 中。以下是我保存 UITextField 信息的方式:
// Handle Save Button
- (void)save
// Get Info From UI
[self.referringObject setValue:self.myInfo.text forKey:@"myInfo"];
就像我之前说的,我已经尝试了几种方法来让它工作,但无法掌握它。我有生以来第一次想对一个无生命的物体造成身体伤害,但我设法克制了自己。
我希望能够将用户放置到 UIImageView 中的图像保存在应用程序的文档文件夹中,然后能够检索它并将其放置在另一个 UIImageView 中,以便在用户将该视图推送到堆栈时显示.非常感谢任何帮助!
【问题讨论】:
【参考方案1】:一切都很好,伙计。不要伤害自己或他人。
您可能不想将这些图像存储在 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];
希望对您有所帮助。
【讨论】:
完全正确 - 只是想提一下 Apple 存储指南,因此取决于图像的性质,它应该存储在缓存下 我听从了你的建议和代码。但它没有出现在照片部分。这是怎么发生的? @DaniloCampos 如何在 Documents Directory 中创建一个文件夹,然后将文件保存在该文件夹中?【参考方案2】: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)
【讨论】:
【参考方案3】:带有扩展的 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")
【讨论】:
【参考方案4】:这是Fangming Ning's answer for Swift 4.2,更新为recommended and more Swifty method 用于检索文档目录路径和更好的文档。也感谢方明宁的新方法。
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)
Check out all the possible Data writing options here.
【讨论】:
这是正确的吗?在回答另一个问题here 时,我发现fileURLWithPath
和absoluteString
是错误的。
@dumbledad 感谢您提供的信息,我已经更新了我的答案并重写了 Swift 4.2 的代码。【参考方案5】:
#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;
【讨论】:
【参考方案6】:在斯威夫特中:
let paths: [NSString?] = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .LocalDomainMask, true)
if let path = paths[0]?.stringByAppendingPathComponent(imageName)
do
try UIImagePNGRepresentation(image)?.writeToFile(path, options: .DataWritingAtomic)
catch
return
【讨论】:
以上是关于从 iOS 上的 UIView 将图像保存到应用程序文档文件夹的主要内容,如果未能解决你的问题,请参考以下文章
iOS:如何将 UIView 的自绘内容转换为图像(普遍的通用解决方案返回空白图像)?
使用 cordova 文件传输将图像/视频保存到 IOS 中的画廊