应用程序在4S上工作正常,但由于SIGABRT而在3G上崩溃

时间:2012-01-31 08:43:43

标签: iphone ios uiimagepickercontroller nsuserdefaults nscoding

当用户第一次启动应用程序时,他会弹出一个并且必须保存图像。它适用于模拟器和4S。但是当我用我的3G开始它时,一旦我选择了一张照片就会给我一个SIGABRT错误。我假设它是因为图片的大小过于挑选并因此声称所有的公羊 - 但这是相当奇怪的,因为我把它做得更小。这是代码:

- (void)viewDidLoad
{ 
    [super viewDidLoad];
    if ([[NSUserDefaults standardUserDefaults] objectForKey:@"bild"] == nil) { 
        picker = [[UIImagePickerController alloc] init];
        picker.delegate = self;
        picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        [self presentModalViewController:picker animated:YES];
    }
}

- (void)imagePickerController:(UIImagePickerController *) Picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    double compressionRatio=1;
    NSData *imageData=UIImageJPEGRepresentation([info objectForKey:@"bild"],compressionRatio);
    while ([imageData length]>5000) { 
        compressionRatio=compressionRatio*0.20;
        imageData=UIImageJPEGRepresentation([info objectForKey:@"bild"],compressionRatio);
    }

    UIImage *yourUIImage;
    yourUIImage = [info objectForKey:UIImagePickerControllerOriginalImage];
    imageData = [NSKeyedArchiver archivedDataWithRootObject:yourUIImage];
    [[NSUserDefaults standardUserDefaults] setObject:imageData forKey:@"bild"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    [self dismissModalViewControllerAnimated:YES];
}

我在此行收到SIGABRT错误imageData = [NSKeyedArchiver archivedDataWithRootObject:yourUIImage];

我应该使用其他方法来调整图像大小吗?或者我应该将其保存为本地文件并在应用程序启动时检索它? (如果可能的话)

3 个答案:

答案 0 :(得分:6)

您正在使用NSCoding将UIImage存档到NSData对象中 在iOS5之前,UIImage没有实现NSCoding的方法。你不能在iOS5之前使用archivedDataWithRootObject:和UIImages 这就是你在iPhone 3G上获得例外的原因。

这只是一个非常有根据的猜测,因为我无法通过文档或设备上的测试确认,但有很多问题和论坛帖子询问如何在UIImage上实现NSCoding。


并且根本没有调用整个代码块,因为[info objectForKey:@"bild"]将返回nil。信息字典不包含密钥bild的对象。 UIImagePickerControllerDelegate_Protocol的文档包含List of valid keys

NSData *imageData=UIImageJPEGRepresentation([info objectForKey:@"bild"],compressionRatio);
while ([imageData length]>5000) { 
    compressionRatio=compressionRatio*0.20;
    imageData=UIImageJPEGRepresentation([info objectForKey:@"bild"],compressionRatio);
}

你可能想要使用类似的东西:

NSData *data;
if ([[UIImage class] conformsToProtocol:@protocol(NSCoding)]) {
    // >= iOS5
    data = [NSKeyedArchiver archivedDataWithRootObject:image];
    // save so you know it's an archived UIImage object
}
else {
    // < iOS5
    data = /* your UIImageJPEGRepresentation method but this time with the key UIImagePickerControllerOriginalImage instead of "bild" */
    // save so you know it's raw JPEG data
}

答案 1 :(得分:3)

编辑:另一个错误可能是你在从图像选择器控制器传递的信息字典中寻找键“bild”的对象。它没有这样的钥匙。您应该传递密钥UIImagePickerControllerOriginalImage来获取图片。

-

你不会丢掉旧的imageData。如果您的问题是高内存消耗,则在逐渐缩小图像时必须取消图像数据。

此外,图像可能太大而无法容纳5000字节。您当前的代码无法正常处理此问题。最终,压缩率将超过1.0,此时该函数可能会抛出异常。

我建议在尝试大量压缩之前调整图像大小。

无论您如何使图像数据变小,您当前的代码都会保留所有旧副本,直到下次自动释放池耗尽为止。由于从UIImageJPEGRepresentation返回的数据是自动释放的,因此您可以尝试在每次循环迭代时使用内联自动释放池来立即排空数据。

答案 2 :(得分:1)

如果SIGABRT始终在imageData = [NSKeyedArchiver archivedDataWithRootObject:yourUIImage];发生,那么我的感觉是它可能是特定的行,而不是内存问题。

UIImage从未习惯于符合NSCoding,但目前的文档说它确实如此。可能是因为限制在iOS 4.2.1中的3G使用的是不符合版本的版本,因此当您尝试存档时崩溃,而iOS 5上的4S则使用新的符合版本。

尝试将一个NSCoding类别添加到UIImage,然后重新运行3G。 http://iphonedevelopment.blogspot.com/2009/03/uiimage-and-nscoding.html

上的示例