Iphone 未释放/覆盖线程中的UIImage
这似乎是扫描iPhone图像的经典方法。我有一个从主线程调度的线程去扫描代码。它本质上是在每次删除UIImage时创建一个新的UIImageIphone 未释放/覆盖线程中的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
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];