从 UIImagePickerController 中选取图像后崩溃(与内存泄漏有关?)

2023-12-01

我一直在尝试最小化我的内存占用UIImagePickerController,但我开始认为我遇到的内存问题是由于内存管理不善造成的,而不是处理内存问题的特定方法UIImagePickerController object.

我的工作流程是这样的:单击“编辑图像”按钮,它会显示一个UIActionSheet。此操作表允许您删除、拍照、从库中选择或取消。如果您选择从库中选择或拍照,我alloc的一个实例UIImagePickerController并展示它,然后发布UIImagePickerController:

-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (actionSheet.tag != 999) {
        UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
        imagePicker.delegate = self;
    
        BOOL pickImage = nil;
    
        if (actionSheet.tag == iPhoneWithDelete) {
            switch (buttonIndex) {
                case 0:
                    object.objectImage = nil;
                    pickImage = NO;
                    break;
                case 1:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
                    pickImage = YES;
                    break;
                case 2:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
                    pickImage = YES;
                    break;
                default:
                    pickImage = NO;
                    break;
            }
        } else if (actionSheet.tag == iPhoneNoDelete) {
            switch (buttonIndex) {
                case 0:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
                    pickImage = YES;
                    break;
                case 1:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
                    pickImage = YES;
                    break;
                default:
                    pickImage = NO;
                    break;
            }       
        } else if (actionSheet.tag == iPodWithDelete) {
            switch (buttonIndex) {
                case 0:
                    object.objectImage = nil;
                    pickImage = NO;
                    break;
                case 1:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
                    pickImage = YES;
                    break;
                default:
                    pickImage = NO;
                    break;
            }
        } else if (actionSheet.tag == iPodNoDelete) {
            switch (buttonIndex) {
                case 0:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
                    pickImage = YES;
                    break;
                default:
                    pickImage = NO;
                    break;
            }
        }
    
        if (pickImage) {
            imagePicker.allowsEditing = YES;
            [self presentModalViewController:imagePicker animated:YES];
        } else {
            [self setupImageButton];
            [self setupChooseImageButton];
        }
        [imagePicker release];
    }
}

一旦我从UIImagePickerController,我将 2 个图像、用于缩略图的已编辑图像的调整大小版本以及原始未编辑图像的 800x600 版本保存到关系属性中(转换,使用在食谱演示代码中找到的相同 UIImage 到 PNG 转换)显示使用:(调整大小方法基于中演示的方法这个帖子.)

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{

    [self dismissModalViewControllerAnimated:YES];

    NSManagedObject *oldImage = object.imageFull;
    if (oldImage != nil)
    {
        [object.managedObjectContext deleteObject:oldImage];
    }

    NSManagedObject *image = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:object.managedObjectContext];
    object.imageFull = image;

    UIImage *rawImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];

    CGSize size = CGSizeMake(800, 600);

    UIImage *fullImage = [UIImageManipulator scaleImage:rawImage toSize:size];

    [image setValue:fullImage forKey:@"imageFull"];

    UIImage *processedImage = [UIImageManipulator scaleImage:[info objectForKey:@"UIImagePickerControllerEditedImage"] toSize:CGSizeMake(75, 75)];
    object.objectImage = processedImage;
    [self setupImageButton];
    [self setupChooseImageButton];

    rawImage = nil;
    fullImage = nil;
    processedImage = nil;
}

当我经过viewDidUnload我正在设置self.object = nil, and [object release] during dealloc,但在大约 10 次图像更改后,我仍然收到内存警告,并在 20 次左右发生崩溃。这让我相信我没有以正确的方式从内存中获取完整图像。我在这里缺少什么?

其次,相机源使用的内存是否比相册源使用的内存多得多?我在使用相机时往往会发生更多崩溃。

--EDIT--

开始赏金any有关我可能处理错误的信息。我将用任何我不清楚的问题的答案来更新这篇文章。我对此无计可施。

--编辑2--

重新编写代码以考虑 chrissr 的建议并实施GCD以提高可用性。这个过程是否如此高效?仍然收到内存警告,并且大约 20 个图像崩溃。我确信做昂贵的组合UIImage调整大小和使用UIImagePickerController正在谋杀 CPU,但我无法想象每个应用程序都在处理围绕 CPU 的不确定性UIImagePickerController。我的内存占用约为 2 兆。我一直假设这会产生大量开销。我应该进一步减少足迹吗?

这是修改后的代码:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{

    [self dismissModalViewControllerAnimated:YES];

    if (object.imagePath != nil) {
        [self deleteImages];
    }
    dispatch_queue_t image_queue;
    image_queue = dispatch_queue_create("com.gordonfontenot.app", NULL);

    dispatch_async(image_queue, ^{
    
        NSDate *now = [NSDate date];
    
        NSDateFormatter *f = [[NSDateFormatter alloc] init];
        [f setDateFormat:@"yyyyMMDDHHmmss"];
    
        NSString *imageName = [NSString stringWithFormat:@"Image-%@-%i", [f stringFromDate:now], arc4random() % 100];
        NSString *thumbName = [NSString stringWithFormat:@"%@-thumb", imageName];
    
        [f release];
    
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
    
        NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:imageName];
        NSString *thumbPath = [documentsDirectory stringByAppendingPathComponent:thumbName];
    
        NSData *thumbImageData = UIImagePNGRepresentation([UIImageManipulator scaleImage:[info objectForKey:@"UIImagePickerControllerEditedImage"] toSize:CGSizeMake(120, 120)]);
        [thumbImageData writeToFile:thumbPath atomically:NO];
        dispatch_async(dispatch_get_main_queue(), ^{
            object.thumbPath = thumbPath;
            [self setupImageButton];
            imageButton.enabled = NO;
            [self setupChooseImageButton];
        });
        NSData *fullImageData = UIImagePNGRepresentation([UIImageManipulator scaleImage:[info objectForKey:@"UIImagePickerControllerOriginalImage"] toSize:CGSizeMake(800, 600)]);
        [fullImageData writeToFile:fullPath atomically:NO];

        dispatch_async(dispatch_get_main_queue(), ^{
            imageButton.enabled = YES;
            object.imagePath = fullPath;
        });
    
        if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
            UIImageWriteToSavedPhotosAlbum([info objectForKey:@"UIImagePickerControllerOriginalImage"], self, nil, nil);
        }
    
    });
    dispatch_release(image_queue);
}

在处理 UIImagePickerController 时,内存警告非常常见。使用相机时尤其如此。请记住,虽然磁盘上的 JPG 或 PNG 可能只有几 MB,但用于绘制图像的内存中未压缩的位图占用的空间要大得多。

您不一定做错了什么,但可以进行一些改进:

与其将图像字节存储在 Core Data 中,为什么不将图像写入磁盘并将文件的路径存储在数据库中呢?

您是否可以找到一种方法来直接管理它们的生命周期并更快地发布它们,而不是使用这么多自动发布的图像?

您最好的选择可能是在处理后尽快将图像写入磁盘并释放它们正在使用的内存。然后使用核心数据而不是原始数据来存储他们的位置。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 UIImagePickerController 中选取图像后崩溃(与内存泄漏有关?) 的相关文章

随机推荐

  • ASP.NET MVC 中的异步 GET/POST 和操作名称冲突

    为 ASP NET MVC 创建编辑页面的推荐方法是在名为 Edit 的控制器上使用两种方法 一种 GET 操作和一种 POST 操作 两者共享相同的名称 但重载方式不同 如果编辑失败 则 POST 操作上会显示验证错误 然后 即使 URL
  • Git克隆ssh,用户名、路径和不同驱动器中带有空格

    我有 3 台 Windows 7 Professional 机器 两台被设置为安装了 Git 的开发机器 一台台式机和一台笔记本电脑 第三个是设置为安装了 Git 的文件服务器 并且它还作为 ssh 服务器运行 我一直在提到 YouTube
  • 如果脚本需要输入或输入密码,则失败

    我正在开发一个不需要与用户交互的脚本 如果我的脚本中的程序需要用户输入某些内容 则该脚本应该失败并立即退出 我已经关闭了STDIN在我的脚本的顶部 这适用于某些命令 但有些命令期望在另一个文件描述符中输入 通常是要求输入密码的命令 例如gi
  • 如何计算8086 IDIV指令的结果?

    说明 十六进制数字 mov ax 0832 mov cx 008a idiv cl 文档说 when operand is a byte AL AX operand AH remainder modulus Source http www
  • 运行 MySql 存储过程的最低访问级别

    我正在尝试设置连接到 MySQL 数据库 8 0 的 NET 4 7 1 程序以使用最低权限运行 NET 程序使用 MySql Data 进行连接 用户执行存储过程的最低权限通常仅为EXECUTE特权 这在 MySQL 工作台或命令行中工作
  • 无法安装 PyZMP for Python -- 依赖项

    我在安装 iPython 的 PyZMP 依赖项时遇到问题 我尝试了很多方法 例如使用 pip brew 但最终还是使用手动安装包这个答案 Now pip list packages产生以下结果 pyzmq 14 2 0 dev pyzmq
  • 为什么在检查字符值是否大于数字时得到 TRUE?

    有人可以向我解释一下这是怎么回事吗 具体来说 为什么我在第一个案例中首先得到 TRUE 为什么与 10 比较时会变成FALSE 9 gt 2 1 TRUE 10 gt 2 1 FALSE 强制转换的层次结构为 逻辑 9 大于 2 but 1
  • 如何在 mongodb 中使用 $in 运算符与 java 中的两个字段

    我想检索以下信息 从数据库中选择姓名 其中地址如 科伦坡 且年龄 gt 20 但对于 Java 中的 MongoDB 来说 本质上 它应该返回所有包含单词 colombo ang Age 大于 20 的名称 我知道 MongoDB 中有 i
  • 如何在android中启用后台数据设置?

    如何以编程方式启用 设置 gt 帐户和同步 gt 后台数据 在冰淇淋三明治里 您无法以编程方式执行此操作 只有用户才有该权限 但是您可以检查他是否启用了使用 ConnectivityManager mgr ConnectivityManag
  • 用新的随机生成的值替换数组中的重复值

    我有下面一个函数 来自上一个问题没有得到答复 创建一个包含 n 个值的数组 数组的总和等于 max function randomDistinctPartition n max partition array for i 1 i lt n
  • WinSCP 在 FTP 服务器上创建目录之前如何检查目录是否存在?

    尝试通过 Jenkins 实现自动化 通过 WinSCP 控制台脚本将文件从本地 Windows 目录传输到 FTP 目录 问题陈述 开始上传前需要检查FTP服务器上是否存在文件夹 这是我试图通过执行的代码winscp script abc
  • 如何知道Google Apps脚本中UrlFetchApp的IP?

    我在 Stackoverflow 上搜索过类似的问题 但他们没有给出答案 我向某个 api 服务发出 UrlFetchApp fetch url 请求 但该服务可能禁止此请求 IP 我需要将其列入白名单 我知道谷歌应用程序使用很多 IP 但
  • ImportError:Celery 3.1 和 Python 2.7 没有名为 celery 的模块

    在 Windows 上使用 Python 2 7 和 Celery 3 1 25 当我们使用以下命令运行 C elery Worker 时 celery A proj worker l info 我们得到错误 ImportError No
  • 在 PHP 中验证 URL 的更好方法

    我一直在阅读 Stack Overflow 上的各种帖子 试图找到一种在 PHP 中验证 URL 的理想方法 我的研究提出了三种可能的解决方案 但是没有一个是理想的 提到的三种方法是正则表达式 filter var url FILTER V
  • vim:更改插入模式下的状态行颜色

    当我进入插入模式时 我发现这个片段可以更改状态行颜色 first enable status line always set laststatus 2 now set it up to change the status line base
  • Selenium+firefox:空的execute_script参数

    我正在尝试设置textarea使用 javascript 代替 send keys 方法来获取值 正如文档所述 我应该能够将 webelement 作为参数传递给execute script 并通过引用此参数arguments大批 但是 我
  • 谷歌可视化-条形图上的点击事件 isStacked: true

    我正在尝试显示条形图的总价值 其中 isStacked true 在 span 当我单击一个栏时位于图表顶部 我探索 google visualization events addListener 功能的参考开始here 当我单击 a 栏时
  • 连接本地MySQL数据库的Python 3.2脚本

    我正在运行 Ubuntu 服务器 我希望它有一个 Python v3 2 CGI 脚本 可以连接到我设置的本地 MySQL 数据库并运行查询 目前 我发现的唯一的东西不支持Python 3 2 请不要建议切换到早期版本的 Python 因为
  • 如何使用 python 将 .blf 数据从 CAN 转换为 .csv

    我有来自 Vector 软件的 blf 格式的 CAN 数据 为了进一步调查 我想使用 python 将其转换为 csv 格式 到目前为止我的进展 import can filename test blf log can BLFReader
  • 从 UIImagePickerController 中选取图像后崩溃(与内存泄漏有关?)

    我一直在尝试最小化我的内存占用UIImagePickerController 但我开始认为我遇到的内存问题是由于内存管理不善造成的 而不是处理内存问题的特定方法UIImagePickerController object 我的工作流程是这样