如何在ARC中释放NSMutableArray保存的数据
How to release NSMutableArray Saved Data in ARC
我有一个使用 ELCImagePickerController 的应用程序。它让我的用户最多选择 6 张图像。我已经保存了这些图像并使用它们来实现整个应用程序中其他视图控制器中的视图。但是,我需要能够在用户返回应用程序的主菜单后释放或以某种方式删除保存的数据,以便他们可以选择 6 张新照片。我刚刚开始学习 NSMutableArrays 和 NSArrays。
在用户返回菜单之前,我想清除按钮操作上的数据。我正在使用 ARC,但我一直没有找到如何在使用 ARC 的同时发布我的数据的方法。任何帮助,将不胜感激。
viewcontroller.m
- (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info
{
[self dismissViewControllerAnimated:YES completion:nil];
for (UIView *v in [_scrollView subviews]) {
[v removeFromSuperview];
}
NSLog(@"info :%@", info);
CGRect workingFrame = _scrollView.frame;
workingFrame.origin.x = 0;
NSMutableArray *images = [NSMutableArray arrayWithCapacity:[info count]];
for (int i =0; i<info.count; i++) {
NSDictionary *dict = [info objectAtIndex:i];
if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypePhoto){
if ([dict objectForKey:UIImagePickerControllerOriginalImage]){
UIImage* image=[dict objectForKey:UIImagePickerControllerOriginalImage];
[images addObject:image];
UIImageView *imageview =[[UIImageView alloc]init];
imageview.image=[images objectAtIndex:i];
[_scrollView addSubview:imageview];
NSString *imagePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *stringWithIndex = [NSString stringWithFormat:@"MainImage%d.jpg", i];
NSString *imageName = [imagePath stringByAppendingPathComponent:stringWithIndex];
NSData *imageData = UIImageJPEGRepresentation(imageview.image, 1.0);
BOOL result = [imageData writeToFile:imageName atomically:YES];
NSLog(@"Saved to %@? %@", imageName, (result? @"YES": @"NO"));
[imageview setContentMode:UIViewContentModeScaleAspectFit];
imageview.frame = workingFrame;
[_scrollView addSubview:imageview];
workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width;
} else {
NSLog(@"UIImagePickerControllerReferenceURL = %@", dict);
}
} else if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypeVideo){
if ([dict objectForKey:UIImagePickerControllerOriginalImage]){
UIImage* image=[dict objectForKey:UIImagePickerControllerOriginalImage];
[images addObject:image];
UIImageView *imageview = [[UIImageView alloc] initWithImage:image];
[imageview setContentMode:UIViewContentModeScaleAspectFit];
imageview.frame = workingFrame;
[_scrollView addSubview:imageview];
workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width;
} else {
NSLog(@"UIImagePickerControllerReferenceURL = %@", dict);
}
} else {
NSLog(@"Uknown asset type");
}
self.chosenImages = images;
}
[_scrollView setPagingEnabled:YES];
[_scrollView setContentSize:CGSizeMake(workingFrame.origin.x, workingFrame.size.height)];
}
prank6ViewController.m
@implementation Prank6ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString *imagePath1 = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *imageName1 = [imagePath1 stringByAppendingPathComponent:@"MainImage5.jpg"];
_prankImageView.image = [UIImage imageWithContentsOfFile:imageName1];
}
- (IBAction)mainMenuActionBtn:(id)sender {
/// Somehow delete all the saved images from the Array...
[self performSegueWithIdentifier:@"mainMenuSegue" sender:self];
}
@end
ARC 只会保留对它们具有强引用的对象。如果您不再希望保留某些内容,则需要删除对它的引用,通常就像将 nil
分配给您持有引用的变量一样简单。
在不详细检查您的代码的情况下声明:
self.chosenImages = nil;
可能是您正在寻找的 - 这将删除对可变数组的引用并且 提供 您没有对数组的其他引用 ARC 将清除它。
另外,您对 elcImagePickerController:
的下一次调用会创建一个新数组并分配给 chosenImages
,并且 ARC 将如上所述清理 chosenImages
引用的先前数组。
HTH
至少,我认为 UIImageJPEGRepresentation returns autoreleased NSData 对象,因此每个 NSData 对象仍然在 Autorelease Pool 上,直到 RunLoop 结束或当前 Autorelease Pool 范围结束的任何地方。使用@autoreleasepool
如下。
@autoreleasepool {
NSData *imageData = UIImageJPEGRepresentation(imageview.image, 1.0);
BOOL result = [imageData writeToFile:imageName atomically:YES];
NSLog(@"Saved to %@? %@", imageName, (result? @"YES": @"NO"));
}
我的问题与 ELCImagePickerController 直接相关。它只是在某一时刻提取了太多数据。这有时 (5/10) 会使应用程序崩溃。
一次拉取 6 张照片,单次查看我的内存使用量为 242MB。我认为内存管理比 ELCImagePickerController 提供的漂亮布局更重要。所以我放弃了它。
我很高兴我做到了。我正在做同样的事情,但让我的用户一次选择一张图片。这使我的视图内存使用量保持在 12MB 以下。总而言之,我很高兴我没有使用它。谢谢您的帮助。
我有一个使用 ELCImagePickerController 的应用程序。它让我的用户最多选择 6 张图像。我已经保存了这些图像并使用它们来实现整个应用程序中其他视图控制器中的视图。但是,我需要能够在用户返回应用程序的主菜单后释放或以某种方式删除保存的数据,以便他们可以选择 6 张新照片。我刚刚开始学习 NSMutableArrays 和 NSArrays。
在用户返回菜单之前,我想清除按钮操作上的数据。我正在使用 ARC,但我一直没有找到如何在使用 ARC 的同时发布我的数据的方法。任何帮助,将不胜感激。
viewcontroller.m
- (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info
{
[self dismissViewControllerAnimated:YES completion:nil];
for (UIView *v in [_scrollView subviews]) {
[v removeFromSuperview];
}
NSLog(@"info :%@", info);
CGRect workingFrame = _scrollView.frame;
workingFrame.origin.x = 0;
NSMutableArray *images = [NSMutableArray arrayWithCapacity:[info count]];
for (int i =0; i<info.count; i++) {
NSDictionary *dict = [info objectAtIndex:i];
if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypePhoto){
if ([dict objectForKey:UIImagePickerControllerOriginalImage]){
UIImage* image=[dict objectForKey:UIImagePickerControllerOriginalImage];
[images addObject:image];
UIImageView *imageview =[[UIImageView alloc]init];
imageview.image=[images objectAtIndex:i];
[_scrollView addSubview:imageview];
NSString *imagePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *stringWithIndex = [NSString stringWithFormat:@"MainImage%d.jpg", i];
NSString *imageName = [imagePath stringByAppendingPathComponent:stringWithIndex];
NSData *imageData = UIImageJPEGRepresentation(imageview.image, 1.0);
BOOL result = [imageData writeToFile:imageName atomically:YES];
NSLog(@"Saved to %@? %@", imageName, (result? @"YES": @"NO"));
[imageview setContentMode:UIViewContentModeScaleAspectFit];
imageview.frame = workingFrame;
[_scrollView addSubview:imageview];
workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width;
} else {
NSLog(@"UIImagePickerControllerReferenceURL = %@", dict);
}
} else if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypeVideo){
if ([dict objectForKey:UIImagePickerControllerOriginalImage]){
UIImage* image=[dict objectForKey:UIImagePickerControllerOriginalImage];
[images addObject:image];
UIImageView *imageview = [[UIImageView alloc] initWithImage:image];
[imageview setContentMode:UIViewContentModeScaleAspectFit];
imageview.frame = workingFrame;
[_scrollView addSubview:imageview];
workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width;
} else {
NSLog(@"UIImagePickerControllerReferenceURL = %@", dict);
}
} else {
NSLog(@"Uknown asset type");
}
self.chosenImages = images;
}
[_scrollView setPagingEnabled:YES];
[_scrollView setContentSize:CGSizeMake(workingFrame.origin.x, workingFrame.size.height)];
}
prank6ViewController.m
@implementation Prank6ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString *imagePath1 = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *imageName1 = [imagePath1 stringByAppendingPathComponent:@"MainImage5.jpg"];
_prankImageView.image = [UIImage imageWithContentsOfFile:imageName1];
}
- (IBAction)mainMenuActionBtn:(id)sender {
/// Somehow delete all the saved images from the Array...
[self performSegueWithIdentifier:@"mainMenuSegue" sender:self];
}
@end
ARC 只会保留对它们具有强引用的对象。如果您不再希望保留某些内容,则需要删除对它的引用,通常就像将 nil
分配给您持有引用的变量一样简单。
在不详细检查您的代码的情况下声明:
self.chosenImages = nil;
可能是您正在寻找的 - 这将删除对可变数组的引用并且 提供 您没有对数组的其他引用 ARC 将清除它。
另外,您对 elcImagePickerController:
的下一次调用会创建一个新数组并分配给 chosenImages
,并且 ARC 将如上所述清理 chosenImages
引用的先前数组。
HTH
至少,我认为 UIImageJPEGRepresentation returns autoreleased NSData 对象,因此每个 NSData 对象仍然在 Autorelease Pool 上,直到 RunLoop 结束或当前 Autorelease Pool 范围结束的任何地方。使用@autoreleasepool
如下。
@autoreleasepool {
NSData *imageData = UIImageJPEGRepresentation(imageview.image, 1.0);
BOOL result = [imageData writeToFile:imageName atomically:YES];
NSLog(@"Saved to %@? %@", imageName, (result? @"YES": @"NO"));
}
我的问题与 ELCImagePickerController 直接相关。它只是在某一时刻提取了太多数据。这有时 (5/10) 会使应用程序崩溃。
一次拉取 6 张照片,单次查看我的内存使用量为 242MB。我认为内存管理比 ELCImagePickerController 提供的漂亮布局更重要。所以我放弃了它。
我很高兴我做到了。我正在做同样的事情,但让我的用户一次选择一张图片。这使我的视图内存使用量保持在 12MB 以下。总而言之,我很高兴我没有使用它。谢谢您的帮助。