我正在编写一个应用程序,用户在其中为自己拍照,然后通过一系列视图使用导航控制器调整图像。如果用户使用前置摄像头拍照(在支持它的设备上设置为默认设置),这非常有效,但是当我重复该过程时,我完成了大约一半,并在抛出内存警告后崩溃。
在 Instruments 中进行分析后,我发现我的应用程序内存占用在使用较低分辨率的前置摄像头图像时保持在 20-25 MB 左右,但是当使用后置摄像头时,每次视图更改都会再增加 33 MB 左右,直到它在大约 350 MB 时崩溃( 4S)
下面是我用来处理将照片保存到文档目录的代码,然后读取该文件位置以将图像设置为UIImageView
. 此代码的“读取”部分通过多个视图控制器 (viewDidLoad) 循环使用,以便将我保存的图像设置为每个视图中的背景图像。
我已经删除了我所有的图像修改代码,以将其减少到试图隔离问题的最低限度,但我似乎找不到它。就目前而言,应用程序所做的只是在第一个视图中拍摄一张照片,然后将该照片用作大约 10 个视图的背景图像,并在用户浏览视图堆栈时进行分配。
现在显然更高分辨率的照片会使用更多的内存,但我不明白的是为什么低分辨率的照片似乎没有使用越来越多的内存,而高分辨率的照片却不断地使用越来越多的内存直到崩溃。
我如何保存和阅读图像:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
jpgData = UIImageJPEGRepresentation(image, 1);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
filePath = [documentsPath stringByAppendingPathComponent:@"image.jpeg"];
[jpgData writeToFile:filePath atomically:YES];
[self dismissModalViewControllerAnimated:YES];
[disableNextButton setEnabled:YES];
jpgData = [NSData dataWithContentsOfFile:filePath];
UIImage *image2 = [UIImage imageWithData:jpgData];
[imageView setImage:image2];
}
现在我知道我可以在保存图像之前尝试缩放图像,我计划接下来研究它,但我不明白为什么这不能按原样工作。也许我错误地认为 ARC 在离开堆栈顶部时会自动释放视图及其子视图。
任何人都可以解释为什么我要堆积我的设备内存吗?(希望我完全忽略了一些简单的事情)我是否设法将ARC扔出窗外?
编辑:我如何在其他视图中调用图像
- (void)loadBackground
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"image.jpeg"];
UIImage *image = [UIImage imageWithContentsOfFile:filePath];
[backgroundImageView setImage:image];
}
我的视图控制器之间的导航是如何建立的:
编辑2:
我的基本声明是什么样的:
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface PhotoPickerViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
{
IBOutlet UIImageView *imageView;
NSData *jpgData;
NSString *filePath;
UIImagePickerController *imagePicker;
IBOutlet UIBarButtonItem *disableNextButton;
}
@end
如果相关,我如何调用我的图像选择器:
- (void)callCameraPicker
{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == YES)
{
NSLog(@"Camera is available and ready");
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
imagePicker.allowsEditing = NO;
imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; for (AVCaptureDevice *device in devices)
{
if([[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2.0)
{
imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
}
}
imagePicker.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:imagePicker animated:YES];
}
else
{
NSLog(@"Camera is not available");
UIAlertView *cameraAlert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"Your device doesn't seem to have a camera!"
delegate:self cancelButtonTitle:@"Dismiss"
otherButtonTitles:nil];
[cameraAlert show];
}
}
编辑 3:我记录了viewDidUnload ,实际上它没有被调用,所以我现在正在调用并loadBackground
在. 我希望这会有所帮助,但没有任何区别。viewWillAppear
backgroundImageView
viewDidDisappear
- (void)viewWillAppear:(BOOL)animated
{
[self loadBackground];
}
- (void)viewDidDisappear:(BOOL)animated
{
NSLog(@"ViewDidDisappear");
backgroundImageView = nil;
}