内存不足时的iOS应用程序行为
我有一个iPhone应用程序。在某些情况下,当设备的可用内存不足时,某些操作(例如,打开相机)可能会导致应用程序崩溃 我的问题是:内存不足时的iOS应用程序行为,ios,iphone,objective-c,memory-management,Ios,Iphone,Objective C,Memory Management,我有一个iPhone应用程序。在某些情况下,当设备的可用内存不足时,某些操作(例如,打开相机)可能会导致应用程序崩溃 我的问题是: 我想防止这些崩溃,应用程序的常见方式是什么 这样做(阻止特定操作、通知用户等) 想法?我这样问是因为我在iOS中没有遇到过这种行为 我遇到的应用程序 是否有任何方法可以防止此类崩溃并保持完整的应用程序功能,如iOS系统调用以释放更多内存等。?如果有人有最佳实践或良好的启发性,我很想听听 编辑:假设我已经实现了“didReceiveMemoryWarning”功能并释
编辑2:我的应用程序是关于图片的。与照相机扫描仪应用程序非常相似,该应用程序允许拍照、图像处理和将相关数据保存在内存中。我的崩溃通常发生在我扫描大量图片时。不,在iOS中没有释放RAM内存的直接调用。如果在项目中使用ARC,将属性正确定义为弱/强等,并检查应用程序是否存在内存泄漏或僵尸进程,则不会出现RAM问题
iOS会从其他应用程序中释放内存,以便在需要时将其分配给前台应用程序,您不应该尝试处理它。如果应用程序因内存问题而崩溃,则应用程序中可能存在内存泄漏。使用仪器来评测你的应用。不,iOS中没有直接调用来释放RAM内存的功能。如果在项目中使用ARC,将属性正确定义为弱/强等,并检查应用程序是否存在内存泄漏或僵尸进程,则不会出现RAM问题
iOS会从其他应用程序中释放内存,以便在需要时将其分配给前台应用程序,您不应该尝试处理它。如果应用程序因内存问题而崩溃,则应用程序中可能存在内存泄漏。使用仪器来评测你的应用程序。自从我开始为iOS开发以来,内存警告系统有了很多改进,ARC在帮助开发人员管理内存方面也非常有效
你应该使用泄漏和分配来分析你的应用程序,以了解你的应用程序消耗如此多内存的原因。
您正在开发哪种应用程序?应该是高内存使用率的应用程序,如游戏或照片应用程序?
崩溃可能是由于对内存警告的响应管理不善,或者是由于占用了大量内存而不会让应用程序喘不过气来。 最常见的原因是图片。如果你不以正确的方式管理这些情况,这些设备将无法处理大量的租用资源,你的应用程序的内存占用将不断增加,直到它无法释放足够的内存
不过,您需要提供更多详细信息。自从我开始为iOS开发以来,内存警告系统有了很多改进,ARC也可以很好地帮助开发人员管理内存
你应该使用泄漏和分配来分析你的应用程序,以了解你的应用程序消耗如此多内存的原因。
您正在开发哪种应用程序?应该是高内存使用率的应用程序,如游戏或照片应用程序?
崩溃可能是由于对内存警告的响应管理不善,或者是由于占用了大量内存而不会让应用程序喘不过气来。 最常见的原因是图片。如果你不以正确的方式管理这些情况,这些设备将无法处理大量的租用资源,你的应用程序的内存占用将不断增加,直到它无法释放足够的内存
不过,您需要提供更多详细信息。我遵循一些经验法则:
//way 1 all on main thread bad approach, basically we are just doing some image manipulation on main thread(should not do on main thread :))
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
YourApplicationDelegate *appDelegate = (YourApplicationDelegate *)[[UIApplication sharedApplication]delegate];
[appDelegate showLandscapeLoading];//think it as progress view/loader
UIImage *pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *imageData = UIImagePNGRepresentation(pickedImage);
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"category_imagename.jpeg"];
NSError * error = nil;
//from here
[imageData writeToFile:path options:NSDataWritingAtomic error:&error];
**//the important part for discussion UI manipulation on main thread bad bad bad**
CGSize size1;//A
size1.width = 400;
size1.height = 400;
UIGraphicsBeginImageContext(size1);
[pickedImage drawInRect:CGRectMake(0, 0, size1.width, size1.height)];
UIImage *bigImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSString *bigThumb = [documentsDirectory stringByAppendingPathComponent:@"category_thumb_imagename.jpeg"];
NSData *data1=UIImageJPEGRepresentation(bigImage, 0.5);
BOOL status1=[data1 writeToFile:bigThumb atomically:YES];
**//up to here should be in non ui thread/seperate thread**
**//below code should go in main thread**
NSLog(@"status1 -> %d",status1);
[self setCategoryImageName:bigImage];
[self.imgCategory setImage:pickedImage];
if (status1) {
isAddingCategoryImage = YES;
}
[appDelegate stopLandscapeLoading];
if (error != nil) {
NSLog(@"Error: %@", error);
return;
}
if ([self.popoverController isPopoverVisible]) {
[self.popoverController dismissPopoverAnimated:true];
}
[picker.view removeFromSuperview];
}
正确的方法是:
使用NSO操作:
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
YourApplicationDelegate *appDelegate = (YourApplicationDelegate *)[[UIApplication sharedApplication]delegate];
[appDelegate showLandscapeLoading];
UIImage *pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSError * error = nil;
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperationWithBlock:^
{
// Create a graphics image context very slow stuff
CGSize newSize = CGSizeMake(400, 400);
UIGraphicsBeginImageContext(newSize);
// Tell the old image to draw in this new context, with the desired
// new size
[pickedImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
// Get the new image from the context
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
// End the context
UIGraphicsEndImageContext();
NSString *bigThumb = [documentsDirectory stringByAppendingPathComponent:@"category_thumb_imagename.jpeg"];
NSData *data1=UIImageJPEGRepresentation(newImage, 0.5);
BOOL status1=[data1 writeToFile:bigThumb atomically:YES];
// ok, now do UI stuff in the main queue
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
[self setCategoryImageName:bigThumb];
[self.imgCategory setImage:pickedImage];
if (status1) {
isAddingCategoryImage = YES;
}
[appDelegate stopLandscapeLoading];
if (error != nil) {
NSLog(@"Error: %@", error);
return;
}
if ([self.popoverController isPopoverVisible]) {
[self.popoverController dismissPopoverAnimated:true];
}
[picker.view removeFromSuperview];
}];
}];
}
感谢和问候,
ALOK我遵循一些经验法则: