1

当用户第一次启动应用程序时,他会弹出一个窗口并且必须保存图像。它适用于模拟器和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];

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

4

3 回答 3

6

您正在使用NSCoding将 UIImage 归档到 NSData 对象中。
在 iOS5 之前 UIImage 没有实现 NSCoding 的方法。在 iOS5 之前,您根本无法archivedDataWithRootObject:与 UIImages 一起使用。
这就是为什么您在 iPhone 3G 上遇到异常的原因。

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


并且这整个代码块根本没有被调用,因为[info objectForKey:@"bild"]will return nil。info 字典不包含 key bild 的对象。文档UIImagePickerControllerDelegate_Protocol包含有效键的列表

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
}
于 2012-01-31T09:18:32.780 回答
3

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

--

你不会扔掉旧的imageData。如果您的问题是高内存消耗,您将不得不在逐步缩小图像时删除图像数据。

此外,图像可能太大而无法容纳在 5000 字节内。您当前的代码不能优雅地处理这个问题。最终,压缩比将超过 1.0,此时函数可能会抛出异常。

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

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

于 2012-01-31T08:55:07.330 回答
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上的示例

于 2012-01-31T09:20:42.187 回答