Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/40.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
Iphone 未释放/覆盖线程中的UIImage_Iphone_Multithreading_Uiimage_Cgimage - Fatal编程技术网

Iphone 未释放/覆盖线程中的UIImage

Iphone 未释放/覆盖线程中的UIImage,iphone,multithreading,uiimage,cgimage,Iphone,Multithreading,Uiimage,Cgimage,这似乎是扫描iPhone图像的经典方法。我有一个从主线程调度的线程去扫描代码。它本质上是在每次删除UIImage时创建一个新的UIImage NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; { while (![thread isCancelled]) { #ifdef DEBUG NSLog(@"Decoding Loop"); #endif // [se

这似乎是扫描iPhone图像的经典方法。我有一个从主线程调度的线程去扫描代码。它本质上是在每次删除UIImage时创建一个新的UIImage

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    { 
        while (![thread isCancelled]) {
#ifdef DEBUG
            NSLog(@"Decoding Loop");
#endif
        //  [self performSelectorOnMainThread:@selector(updateImageBuffer) withObject:nil waitUntilDone:YES];           
            CGImageRef cgScreen = UIGetScreenImage();
            UIImage *uiimage = [UIImage imageWithCGImage:cgScreen];

            if (uiimage){
                CGSize size = [uiimage size];
                CGRect cropRect = CGRectMake(0.0, 80.0, size.width, 360); // Crop to centre of the screen - makes it more robust
#ifdef DEBUG
                NSLog(@"picked image size = (%f, %f)", size.width, size.height);
#endif
                [decoder decodeImage:uiimage cropRect:cropRect];
            }
            [uiimage release];
            CGImageRelease(cgScreen);
        }
    }
    [pool release];
问题是[pool release]会导致一个错误\u BAD\u EXC(这是一个古老的经典)和程序爆炸。我被告知没有必要调用[uiimage release],因为我还没有明确分配uiimage,但情况似乎并非如此。如果我把这一行去掉,内存的使用就会大大增加,程序会因为内存不足而退出。看来我不能以我喜欢的方式完成这项工作

有没有办法“就地”创建UIImage?也就是说,是否有一个作为UIImage一次又一次写入的缓冲区?我想这样行吗

更新

已尝试在主线程上执行UIKit相关调用,如下所示:

-(void)performDecode:(id)arg{

    // Perform the decoding in a seperate thread. This should, in theory, bounce back with a 
    // decoded or not decoded message. We can quit at the end of this thread.
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    { 
        while (![thread isCancelled]) {

#ifdef DEBUG
            NSLog(@"Decoding Loop");
#endif
            [self performSelectorOnMainThread:@selector(updateImageBuffer) withObject:nil waitUntilDone:YES];           

            if (uiimage){
                CGSize size = [uiimage size];
                CGRect cropRect = CGRectMake(0.0, 80.0, 320, 360); // Crop to centre of the screen - makes it more robust
#ifdef DEBUG
                NSLog(@"picked image size = (%f, %f)", size.width, size.height);
#endif
                [decoder decodeImage:uiimage cropRect:cropRect];
            }
        }
    }
    [pool drain];


#ifdef DEBUG
    NSLog(@"finished decoding.");
#endif


}

-(void) updateImageBuffer {
    CGImageRef cgScreen = UIGetScreenImage();
    uiimage = [UIImage imageWithCGImage:cgScreen];
    //[uiimage release];
    CGImageRelease(cgScreen);
}

然而,当一个人想要抓住UIImage的“尺寸”时,EXC_BAD_ACCESS会抬起它丑陋的头,这是毫无乐趣的。在这种情况下,这肯定是错误的。此外,Apple强调所有UIKit方法都必须在主线程上执行。这包括
UIGetScreenImage()
+[UIImage imageWithCGImage::

编辑:因此在错误的线程上调用
-[UIImage size]
时会出现异常。这可能不会让您感到惊讶,因为这是不允许的。

UIGetScreenImage()是私有的,没有文档记录,因此您完全不能使用它。如果你没有提到它,那说明你现在拥有CGImageRef cgScreen,那么你为什么要发布它呢?您也无法知道它是否是线程安全的,因此应该假设它不是。然后,您继续发布IImage*uiimage,您没有初始化、保留或复制它,所以再次声明—您不拥有它。回顾历史

明确地说我最清楚什么时候释放这个对象似乎是可行的。虚拟内存仍在增加,但物理内存现在保持不变。感谢您指出UIKit线程安全问题。这是我错过的一点,但似乎并不影响目前的跑步


另外,我应该指出,红色激光和Quickmark都使用这种扫描相机信息的方法;)

正如其他人所说,您不应该释放imageWithCGImage:返回的UIImage。它是自动释放的。当您的池耗尽时,它会尝试向已释放的映像对象发送释放消息,从而导致崩溃

内存使用率不断攀升的原因是,您只会将自动释放池排出循环之外。自动释放的对象在循环中不断累积。(顺便说一下,您需要在该方法结束时释放您的自动释放池,因为它当前正在泄漏。)为了防止这种累积,您可以在循环中定期排空池


但是,我建议切换到执行
[[UIImage alloc]initWithCGImage:cgScreen]
,然后在完成后释放图像。我尽量避免在iPhone应用程序中使用自动释放的对象,以便更严格地控制内存使用和整体性能。

私有或非私有与我无关。cgScreen上的发布方法取自另一段代码。我已经审阅了文档,我同意uiimage不应该被发布,但是正如我所说的,如果这条线没有放好的话,内存就会不断增加是的,这就是我的想法。我删掉了,但我使用的内部库也在对UIImage做这样的事情,所以。。。那件事没有乐趣,干杯!我在前面的评论中提到了这一点,但感谢您提供的关于排水管的提示。关键是要弄清楚,方便的方法坚持自动释放,因此,提前释放是不正确的。
UIImage *uiimage = [[UIImage alloc] initWithCGImage: cgScreen];