iOS 4 的错误?保存到文件夹中的图像文件在保存随机数量的图像后将被覆盖
我有一个应用程序(SDK 4.3),它可以将图像保存为谷歌地图上航路点的附件。 文件保存是非常标准的(据我所知)UIImagePickerController 代码。 我没有将图像保存到相机胶卷,而是将缩略图保存到子文件夹中。我需要那个。 在看似随机的点上,根本没有捕获和记录错误,图像不会保存到文件夹中,而是覆盖以前保存的图像文件! 整个世界看起来就像是一场先进先出的流行音乐。 这非常奇怪,我什至构建了一个小型测试应用程序,并在幽灵出现时立即启动它......将一系列相机图像保存到相同的文件夹中,但看到相同的效果。一旦达到随机魔法文件编号,图像就会被覆盖! 随机是指在保存 7 个图像后,覆盖开始......甚至在手机重新启动后也能确保内存泄漏不是问题。擦除APP并重试... 这次会在保存 16 或 23 个图像文件后发生。 我已经走了各种极端,却找不到问题的根源。 在小测试APP中,我也用同样的方法保存到相机胶卷中。它将保存在那里,但会覆盖该文件夹。文件名是随机生成的 10 个字符的字母数字。
我现在倾向于将其理解为一个错误。我总是可以重现该错误,但无法预测。它是随机出现的。
当我撕扯头发时,我将不胜感激。
这是代码...
//tester.h
#import <UIKit/UIKit.h>
@interface tester : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
{
UIImagePickerController *imgPicker;
IBOutlet UIButton *pressit;
IBOutlet UIButton *seeya;
UIActivityIndicatorView *activity;
}
@property (retain )UIImagePickerController *imgPicker;
@property (nonatomic,retain)IBOutlet UIButton *pressit;
@property (nonatomic,retain)IBOutlet UIButton *seeya;
@property (nonatomic,retain)UIActivityIndicatorView *activity;
-(NSString *) genRandStringLength:(int) len ;
-(void)saveImagesFromPickerInTheBackgroundUsingImage:(UIImage *)img;
-(NSArray *)buildFilePaths;
- (IBAction)snapShots:(UIButton *)button;
-(IBAction)byebye:(id)sender;
@end
//=====================
//tester.m
#import "tester.h"
#import "MultiMediaUtilities.h"
@implementation tester
@synthesize imgPicker;
@synthesize pressit,seeya,activity;
//Image size constants
#define MAX_THUMBNAIL_RES_SIZE 103
#define MAX_IMAGE_RES_SIZE 640
- (IBAction)snapShots:(UIButton *)button
{
if (!imgPicker) imgPicker = [[UIImagePickerController alloc]init];
imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imgPicker.delegate = self;
[self presentModalViewController:imgPicker animated:YES];
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *memoImage = [[MultiMediaUtilities scaleAndRotateImage:[info objectForKey:@"UIImagePickerControllerOriginalImage"] toResolution:MAX_IMAGE_RES_SIZE ]retain];
UIImageWriteToSavedPhotosAlbum(memoImage, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
[self saveImagesFromPickerInTheBackgroundUsingImage:memoImage];
// Dismiss the camera
[self dismissModalViewControllerAnimated:YES];
}
//builds paths to files in system with components
-(NSArray *)buildFilePaths
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *docsPath = [documentsDirectory stringByAppendingPathComponent:@"imagesfolder"];
NSString *fullDocsPath = [docsPath stringByAppendingPathComponent:@"assets"];
NSString *fullThumbsPath = [fullDocsPath stringByAppendingPathComponent:@"thumbs"];
NSArray * retArray = [NSArray arrayWithObjects:fullDocsPath,fullThumbsPath,nil];
return retArray;
}
-(void)saveImagesFromPickerInTheBackgroundUsingImage:(UIImage *)img
{
@try
{
NSFileManager *NSFm = [NSFileManager defaultManager];
NSArray *pathsArray = [NSArray arrayWithArray:[self buildFilePaths]];
NSString *fullDocsPath = [NSString stringWithFormat:@"%@", (NSString *)[pathsArray objectAtIndex:0]];
NSString *fullThumbsPath = [NSString stringWithFormat:@"%@", (NSString *)[pathsArray objectAtIndex:1]];
//Ensure Folders exist
BOOL isDir=YES;
NSError *error;
if(![NSFm fileExistsAtPath:fullDocsPath isDirectory:&isDir])
if(![NSFm createDirectoryAtPath:fullDocsPath withIntermediateDirectories:YES attributes:nil error:&error])
NSLog(@"Error: Create Images folder failed");
//create thumbs folder too
if(![NSFm fileExistsAtPath:fullThumbsPath isDirectory:&isDir])
if(![NSFm createDirectoryAtPath:fullThumbsPath withIntermediateDirectories:YES attributes:nil error:&error])
NSLog(@"Error: Create Thumbs folder failed");
//build the filenames & paths
NSString *newImageName= [NSString stringWithFormat:@"%@.png", [self genRandStringLength:10]];
NSString *imagePath = [[fullDocsPath stringByAppendingPathComponent:newImageName]retain];
NSLog(@"SavingIMage ImagePath = %@",imagePath);
NSString *thumbPath = [[fullThumbsPath stringByAppendingPathComponent:newImageName]retain];
NSLog(@"SavingIMage thumbPAth = %@",thumbPath);
//Write the files out
NSData *imgData = UIImagePNGRepresentation(img);
[imgData writeToFile:imagePath options:NSDataWritingAtomic error:&error];
if (!error) {
NSLog(@"Error writing image %@",error.description);
}
NSData *thumbData = UIImagePNGRepresentation(img);
[thumbData writeToFile:thumbPath options:NSDataWritingAtomic error:&error];
if (!error) {
NSLog(@"Error writing thumb %@",error.description);
}
}
@catch (NSException * e)
{
NSLog(@"Exception: %@", e);
}
}
-(NSString *) genRandStringLength:(int) len
{
NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
NSMutableString *randomString = [NSMutableString stringWithCapacity: len];
for (int i=0; i<len; i++)
{
[randomString appendFormat: @"%c", [letters characterAtIndex: rand()%[letters length]]];
}
return randomString;
}
- (void)image:(UIImage*)image didFinishSavingWithError:(NSError *)error contextInfo:(NSDictionary*)info {
NSString *message;
NSString *title;
if (!error)
{
title = @"Camera...";
message = @"Image saved!...Just as well.";
}
else
{
title = @"Error";
message = [error description];
}
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:title
message:message
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
if (image !=NULL){
[image release];
image=nil;
}
if(info !=NULL)
{
[info release];
info=nil;
}
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(void)dealloc
{
[imgPicker release];
[pressit release];
[seeya release];
[activity release];
[super dealloc];
}
@end
I have an APP (SDK 4.3) which saves images being attachmemnts for a waypoint on a google map.
The file save is pretty standard (afaik) UIImagePickerController code.
Rather than saving to the camera roll I was saving the image and then the thumbnail to a subfolder. I need that.
At seemingly random points with no errors being trapped at all and logged, the images will not save to the folder but instead over-write previously saved image files!
It looks for all the world like a FIFO pop going on.
It is seriously odd and I have even built a small test APP and fired it up as soon as the spookiness appeared...saving a series of camera images to the same folders but see the same effect. The images get over-written once the random magic file number is reached!
Random in the sense that after 7 saved images, the overwriting begins...even after a reboot of the phone to ensure memory leaks is not the issue. Wipe the APP and try again...
This time it will happen after 16 oR 23 image files saved.
I have gone to all sorts of extremes and cannot find the source of the issue.
In the small test APP, in the same method I save out to the camera roll as well. It will save there but overwrite in the folder. The file names are 10 character random generated alpha-numeric.
I am now leaning to understand this as a bug. I can always reproduce the error but not predictably. It arises randomly.
I would appreciate help as I am tearing my hair out.
Here is the code...
//tester.h
#import <UIKit/UIKit.h>
@interface tester : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
{
UIImagePickerController *imgPicker;
IBOutlet UIButton *pressit;
IBOutlet UIButton *seeya;
UIActivityIndicatorView *activity;
}
@property (retain )UIImagePickerController *imgPicker;
@property (nonatomic,retain)IBOutlet UIButton *pressit;
@property (nonatomic,retain)IBOutlet UIButton *seeya;
@property (nonatomic,retain)UIActivityIndicatorView *activity;
-(NSString *) genRandStringLength:(int) len ;
-(void)saveImagesFromPickerInTheBackgroundUsingImage:(UIImage *)img;
-(NSArray *)buildFilePaths;
- (IBAction)snapShots:(UIButton *)button;
-(IBAction)byebye:(id)sender;
@end
//=====================
//tester.m
#import "tester.h"
#import "MultiMediaUtilities.h"
@implementation tester
@synthesize imgPicker;
@synthesize pressit,seeya,activity;
//Image size constants
#define MAX_THUMBNAIL_RES_SIZE 103
#define MAX_IMAGE_RES_SIZE 640
- (IBAction)snapShots:(UIButton *)button
{
if (!imgPicker) imgPicker = [[UIImagePickerController alloc]init];
imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imgPicker.delegate = self;
[self presentModalViewController:imgPicker animated:YES];
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *memoImage = [[MultiMediaUtilities scaleAndRotateImage:[info objectForKey:@"UIImagePickerControllerOriginalImage"] toResolution:MAX_IMAGE_RES_SIZE ]retain];
UIImageWriteToSavedPhotosAlbum(memoImage, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
[self saveImagesFromPickerInTheBackgroundUsingImage:memoImage];
// Dismiss the camera
[self dismissModalViewControllerAnimated:YES];
}
//builds paths to files in system with components
-(NSArray *)buildFilePaths
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *docsPath = [documentsDirectory stringByAppendingPathComponent:@"imagesfolder"];
NSString *fullDocsPath = [docsPath stringByAppendingPathComponent:@"assets"];
NSString *fullThumbsPath = [fullDocsPath stringByAppendingPathComponent:@"thumbs"];
NSArray * retArray = [NSArray arrayWithObjects:fullDocsPath,fullThumbsPath,nil];
return retArray;
}
-(void)saveImagesFromPickerInTheBackgroundUsingImage:(UIImage *)img
{
@try
{
NSFileManager *NSFm = [NSFileManager defaultManager];
NSArray *pathsArray = [NSArray arrayWithArray:[self buildFilePaths]];
NSString *fullDocsPath = [NSString stringWithFormat:@"%@", (NSString *)[pathsArray objectAtIndex:0]];
NSString *fullThumbsPath = [NSString stringWithFormat:@"%@", (NSString *)[pathsArray objectAtIndex:1]];
//Ensure Folders exist
BOOL isDir=YES;
NSError *error;
if(![NSFm fileExistsAtPath:fullDocsPath isDirectory:&isDir])
if(![NSFm createDirectoryAtPath:fullDocsPath withIntermediateDirectories:YES attributes:nil error:&error])
NSLog(@"Error: Create Images folder failed");
//create thumbs folder too
if(![NSFm fileExistsAtPath:fullThumbsPath isDirectory:&isDir])
if(![NSFm createDirectoryAtPath:fullThumbsPath withIntermediateDirectories:YES attributes:nil error:&error])
NSLog(@"Error: Create Thumbs folder failed");
//build the filenames & paths
NSString *newImageName= [NSString stringWithFormat:@"%@.png", [self genRandStringLength:10]];
NSString *imagePath = [[fullDocsPath stringByAppendingPathComponent:newImageName]retain];
NSLog(@"SavingIMage ImagePath = %@",imagePath);
NSString *thumbPath = [[fullThumbsPath stringByAppendingPathComponent:newImageName]retain];
NSLog(@"SavingIMage thumbPAth = %@",thumbPath);
//Write the files out
NSData *imgData = UIImagePNGRepresentation(img);
[imgData writeToFile:imagePath options:NSDataWritingAtomic error:&error];
if (!error) {
NSLog(@"Error writing image %@",error.description);
}
NSData *thumbData = UIImagePNGRepresentation(img);
[thumbData writeToFile:thumbPath options:NSDataWritingAtomic error:&error];
if (!error) {
NSLog(@"Error writing thumb %@",error.description);
}
}
@catch (NSException * e)
{
NSLog(@"Exception: %@", e);
}
}
-(NSString *) genRandStringLength:(int) len
{
NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
NSMutableString *randomString = [NSMutableString stringWithCapacity: len];
for (int i=0; i<len; i++)
{
[randomString appendFormat: @"%c", [letters characterAtIndex: rand()%[letters length]]];
}
return randomString;
}
- (void)image:(UIImage*)image didFinishSavingWithError:(NSError *)error contextInfo:(NSDictionary*)info {
NSString *message;
NSString *title;
if (!error)
{
title = @"Camera...";
message = @"Image saved!...Just as well.";
}
else
{
title = @"Error";
message = [error description];
}
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:title
message:message
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
if (image !=NULL){
[image release];
image=nil;
}
if(info !=NULL)
{
[info release];
info=nil;
}
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(void)dealloc
{
[imgPicker release];
[pressit release];
[seeya release];
[activity release];
[super dealloc];
}
@end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
即使是种子,这也是对随机数的不当使用。
三种方法:
[[NSProcessInfo processInfo]globalUniqueString]
中的 UUIDEven seeded, this is an inappropriate use of random numbers.
Three approaches:
[[NSProcessInfo processInfo] globallyUniqueString]
正如 Mats 所说,如果您不使用 srand 初始化随机数生成器,则 rand() 会表现得很奇怪,并且不会期望它生成随机数。这可能会导致您遇到相同的文件名。
As Mats said, if you don't initialize your random number generator with srand, rand() will behave strangely and don't expect it to generate random numbers. This can cause the same filenames you experience.