【问题标题】:iOS 4 bug? Image files saved to folder are overwritten after a random number of images savediOS 4 错误?保存到文件夹的图像文件在保存随机数量的图像后被覆盖
【发布时间】:2011-10-15 11:42:27
【问题描述】:

我有一个 APP (SDK 4.3),可以将图像保存为谷歌地图上的航路点的附件。 文件保存是非常标准的(afaik)UIImagePickerController 代码。 我没有保存到相机胶卷,而是保存图像,然后将缩略图保存到子文件夹。我需要它。 在看似随机的点,完全没有错误被捕获和记录,图像不会保存到文件夹中,而是覆盖以前保存的图像文件! 它像 FIFO 流行一样寻找整个世界。 这很奇怪,我什至构建了一个小型测试应用程序,并在幽灵出现时立即启动它......将一系列相机图像保存到相同的文件夹但看到相同的效果。一旦达到随机魔术文件编号,图像就会被覆盖! 从某种意义上说是随机的,即在保存 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

【问题讨论】:

  • 你为什么用rand()而不是random()?你如何设置种子?

标签: objective-c xcode file-io ios4


【解决方案1】:

即使是种子,这也是对随机数的不当使用。

三种方法:

  1. 使用递增的序列号。 (1、2、3 等)
  2. 使用来自[[NSProcessInfo processInfo] globallyUniqueString] 的 UUID
  3. 使用根据日期和时间构造的文件名。

【讨论】:

  • 是的,非常感谢。我没有意识到 random 是未播种的。 arcrand 工作正常。这真的把我打败了。我在想什么。对不起,我放弃了这个问题。我真的很感谢你花时间史蒂文。干杯
  • 重新阅读我的答案,感谢您以有益的精神阅读它,而不是我写它的相当简短的方式。 :)
【解决方案2】:

正如 Mats 所说,如果您不使用 srand 初始化随机数生成器,rand() 会表现得很奇怪,并且不要期望它会生成随机数。这可能会导致您遇到相同的文件名。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-27
    • 1970-01-01
    • 2021-12-26
    • 2019-04-10
    • 2014-12-11
    • 1970-01-01
    相关资源
    最近更新 更多