Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/107.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
内存不足时的iOS应用程序行为_Ios_Iphone_Objective C_Memory Management - Fatal编程技术网

内存不足时的iOS应用程序行为

内存不足时的iOS应用程序行为,ios,iphone,objective-c,memory-management,Ios,Iphone,Objective C,Memory Management,我有一个iPhone应用程序。在某些情况下,当设备的可用内存不足时,某些操作(例如,打开相机)可能会导致应用程序崩溃 我的问题是: 我想防止这些崩溃,应用程序的常见方式是什么 这样做(阻止特定操作、通知用户等) 想法?我这样问是因为我在iOS中没有遇到过这种行为 我遇到的应用程序 是否有任何方法可以防止此类崩溃并保持完整的应用程序功能,如iOS系统调用以释放更多内存等。?如果有人有最佳实践或良好的启发性,我很想听听 编辑:假设我已经实现了“didReceiveMemoryWarning”功能并释

我有一个iPhone应用程序。在某些情况下,当设备的可用内存不足时,某些操作(例如,打开相机)可能会导致应用程序崩溃

我的问题是:

  • 我想防止这些崩溃,应用程序的常见方式是什么 这样做(阻止特定操作、通知用户等) 想法?我这样问是因为我在iOS中没有遇到过这种行为 我遇到的应用程序
  • 是否有任何方法可以防止此类崩溃并保持完整的应用程序功能,如iOS系统调用以释放更多内存等。?如果有人有最佳实践或良好的启发性,我很想听听
  • 编辑:假设我已经实现了“didReceiveMemoryWarning”功能并释放了所有可以释放的内存,我会问这个问题


    编辑2:我的应用程序是关于图片的。与照相机扫描仪应用程序非常相似,该应用程序允许拍照、图像处理和将相关数据保存在内存中。我的崩溃通常发生在我扫描大量图片时。

    不,在iOS中没有释放RAM内存的直接调用。如果在项目中使用ARC,将属性正确定义为弱/强等,并检查应用程序是否存在内存泄漏或僵尸进程,则不会出现RAM问题


    iOS会从其他应用程序中释放内存,以便在需要时将其分配给前台应用程序,您不应该尝试处理它。如果应用程序因内存问题而崩溃,则应用程序中可能存在内存泄漏。使用仪器来评测你的应用。

    不,iOS中没有直接调用来释放RAM内存的功能。如果在项目中使用ARC,将属性正确定义为弱/强等,并检查应用程序是否存在内存泄漏或僵尸进程,则不会出现RAM问题


    iOS会从其他应用程序中释放内存,以便在需要时将其分配给前台应用程序,您不应该尝试处理它。如果应用程序因内存问题而崩溃,则应用程序中可能存在内存泄漏。使用仪器来评测你的应用程序。

    自从我开始为iOS开发以来,内存警告系统有了很多改进,ARC在帮助开发人员管理内存方面也非常有效
    你应该使用泄漏和分配来分析你的应用程序,以了解你的应用程序消耗如此多内存的原因。
    您正在开发哪种应用程序?应该是高内存使用率的应用程序,如游戏或照片应用程序?
    崩溃可能是由于对内存警告的响应管理不善,或者是由于占用了大量内存而不会让应用程序喘不过气来。 最常见的原因是图片。如果你不以正确的方式管理这些情况,这些设备将无法处理大量的租用资源,你的应用程序的内存占用将不断增加,直到它无法释放足够的内存


    不过,您需要提供更多详细信息。

    自从我开始为iOS开发以来,内存警告系统有了很多改进,ARC也可以很好地帮助开发人员管理内存
    你应该使用泄漏和分配来分析你的应用程序,以了解你的应用程序消耗如此多内存的原因。
    您正在开发哪种应用程序?应该是高内存使用率的应用程序,如游戏或照片应用程序?
    崩溃可能是由于对内存警告的响应管理不善,或者是由于占用了大量内存而不会让应用程序喘不过气来。 最常见的原因是图片。如果你不以正确的方式管理这些情况,这些设备将无法处理大量的租用资源,你的应用程序的内存占用将不断增加,直到它无法释放足够的内存


    不过,您需要提供更多详细信息。

    我遵循一些经验法则:

  • 使用弧

  • 对IBOutlet(顶层示例:UIwindow除外)和代理使用弱

  • 对类属性使用Strong,对NSString使用copy

  • 不要直接访问变量,使用self…方式

  • 不要使用自动释放方式创建新对象,例如NSArray*数组=[NSArray arrayWithObjects……,而是使用NSArray*数组=[NSArray alloc]initWit

    NSString类的方法相同。请尝试使用[NSString alloc]initWithFormat…..而不是[NSString stringWithFormat]

  • 当您添加NSNotification(addObserver…)时,中心必须在dealloc中删除(removeObserver…)它们

  • 实施didReceiveMemoryWarning(视图控制器级别)或applicationDidReceiveMemoryWarning(应用程序级别,它比视图控制器级别先调用)正确地说,有时您只希望从崩溃中保存。您可以显示一个警报,告诉用户可用内存不足,您可以弹出/显示..用户到主屏幕。(错误做法)

  • 在后台线程中,不要对主线程执行任何操作。始终对后台线程使用@autorelease块

  • 对长时间运行的进程使用GCD/NSO操作队列

  • 请密切关注您正在使用的图像资源,仅使用所需大小的图像,而不要根据需要将大图像缩放到小图像大小

  • 对长时间运行的循环使用自动释放池,这会创建许多自动释放的对象

  • 我为您准备了一些ypu可以遵循的代码片段:

        //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

    我遵循一些经验法则:

  • 使用弧

  • 对IBOutlet(顶层示例:UIwindow除外)和代理使用弱

  • 对类属性使用Strong,对NSString使用copy

  • 不要直接访问变量,使用self…方式

  • 不要使用自动释放方式创建新对象,例如NSArray*数组=[NSArray arrayWithObjects……,而是使用NSArray*数组=[NSArray alloc]initWit

    NSString类的方法相同。请尝试使用[NSString alloc]initWithFormat…..而不是o