繁体   English   中英

在设备上运行应用程序时出现“收到内存警告”

[英]“Received memory warning” while running app on device

我正在开发iPhone视频解码器应用程序。 我需要为每个帧转换原始像素数据,并在屏幕上连续渲染(因此形成视频)。 下面的功能是一种在屏幕上渲染每一帧的功能。

   - (void)drawBufferWidth:(int)width height:(int)height pixels:(unsigned char*)pixels
    {

         CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

         CGContextRef gtx = CGBitmapContextCreate(pixels, width, height, BitsPerComponent, BytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
         CGColorSpaceRelease(colorSpace);   

         myimage = CGBitmapContextCreateImage(gtx); //myimage is of type CGImageRef
         CGContextRelease(gtx);

         img.image = [UIImage imageWithCGImage:myimage]; //img is of type UIImageView
         [CATransaction flush];
         CGImageRelease(myimage);

         myimage = Nil;
    }

该代码在模拟器上可以正常工作。 当我在设备上运行它时,它显示几帧,并显示“接收到内存警告”并崩溃。

我无法弄清楚问题出在哪里。 我是否没有正确分配内存,或者即使我释放映像,映像仍存在于内存中,从而耗尽了内存?

请帮助!

提前致谢。

编辑:

Xcode组织者说:

hevcd[665] has active assertions beyond permitted time: 
{(
    <SBProcessAssertion: 0x11aacf70> identifier: Suspending process: hevcd[665] permittedBackgroundDuration: 10.000000 reason: suspend owner pid:565 preventSuspend  preventThrottleDownCPU  preventThrottleDownUI 
)}

一些观察:

  1. 假设您有一个for循环:

     for (i = start; i < end; i++) { // doing lots of memory intensive stuff } 

    您必须认识到,在该循环过程中自动释放的任何内存实际上都不会退还给操作系统,直到该循环完成并且刷新自动释放池为止。 理论上,当执行内存密集型操作时,您可以执行以下操作:

     for (i = start; i < end; i++) { @autorelease { // doing lots of memory intensive stuff } } 

    这样,您可以手动创建一个新的自动释放池,该池将以更高的频率刷新。

  2. 话虽如此,您实际上不应该执行长时间的任务,这些任务不会退回到操作系统上(至少在主线程上,并且因为您正在执行UI事务,所以必须在主线程上执行此操作)。 与执行延长for循环相比,更好的模型是让操作系统每隔一定的时间间隔调用代码。 然后,标准的自动释放池就可以完成工作,您应该会很好。 您可以这样创建一个计时器:

     - (void)startTimer { self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(handleTimer:) userInfo:nil repeats:YES]; } 

    然后,您有一个例程来处理计时器:

     - (void)handleTimer:(NSTimer *)timer { // do what you need here } 

    确保关闭计时器(例如,当视图消失时),否则关闭该视图控制器时,将不会释放它,因为计时器将保持对它的强烈引用,并且您将拥有一个保留周期(或强大的参考周期),您将泄漏内存。

     - (void)viewWillDisappear:(BOOL)animated { [self.timer invalidate]; } 
  3. 您也可以使用CADisplayLink实现类似的功能。 您可以创建显示链接:

     - (void)startDisplayLink { self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)]; [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; } - (void)handleDisplayLink:(CADisplayLink *)displayLink { // do what you need here } 

    再次,您需要确保在完成后将其停止:

     - (void)viewWillDisappear:(BOOL)animated { [self.displayLink invalidate]; } 

所有这三种情况都可能会纠正您的内存状况(除非您有一些未检测到的保留周期或泄漏)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM