2012-03-02 121 views
0

我正在开发一个应用程序,其中我的桌面视图中显示了很多图像。这些图像必须来自服务器,因此我创建了另一个线程,在该线程中图像得到处理然后在表格视图单元格上进行设置,以使我们的表格视图顺利且正确地滚动。 我的问题是,当我滚动我的表视图的次数,应用程序获得冻结,一段时间后,Xcode的显示下图所示的消息: - enter image description here多个NSThreads同时运行导致应用程序冻结

My table view cell code :- 

    id object = [imageDictFunctionApp objectForKey:[NSString stringWithFormat:@"%d",functionAppButton.tag]]; 
        if(!object){  

         NSArray *catdictObject=[NSArray arrayWithObjects:[NSNumber numberWithInt:functionAppButton.tag],indexPath,[NSNumber numberWithInt:i],nil]; 
         NSArray *catdictKey=[NSArray arrayWithObjects:@"btn",@"indexPath",@"no",nil]; 
         NSDictionary *catPassdict=[NSDictionary dictionaryWithObjects:catdictObject forKeys:catdictKey]; 
         [NSThread detachNewThreadSelector:@selector(displayingSmallImageForFunctionsApps:) toTarget:self withObject:catPassdict]; 

        } 
        else 
        { 
         if(![object isKindOfClass:[NSNull class]]){ 
          UIImage *img = (UIImage *)object; 
          [functionAppButton setImage:img forState:UIControlStateNormal]; 
         } 


-(void)displayingSmallImageForFunctionsApps:(NSDictionary *)dict 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    NSIndexPath *path=[dict objectForKey:@"indexPath"]; 
    NSArray *catArray=[self.functionDataDictionary objectForKey:[self.functionsKeysArray objectAtIndex:path.row]]; 
    int vlaue=[[dict objectForKey:@"no"] intValue]; 
    NSDictionary *dict1=[catArray objectAtIndex:vlaue]; 
    NSString *urlString=[dict1 objectForKey:@"artwork_url_large"]; 
    NSURL *url = [NSURL URLWithString:urlString]; 
    UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]]; 

    if(image){ 
     [imageDictFunctionApp setObject:image forKey:[NSString stringWithFormat:@"%d",[[dict objectForKey:@"btn"] intValue]]]; 
     NSMutableDictionary *dict2=[NSMutableDictionary dictionaryWithCapacity:4]; 
     [dict2 setObject:image forKey:@"imageValue"]; 
     [dict2 setObject:[dict objectForKey:@"btn"] forKey:@"tag"]; 
     [dict2 setObject:[dict objectForKey:@"indexPath"] forKey:@"indexPath"]; 
     [self performSelectorOnMainThread:@selector(setImageInCellDictCategroryTable:) withObject:dict2 waitUntilDone:NO]; 


    } 
    else{ 
     [imageDictFunctionApp setObject:[NSNull null] forKey:[NSString stringWithFormat:@"%d",[[dict objectForKey:@"btn"] intValue]]]; 
    } 

    [pool drain]; 

} 

- (void)setImageInCellDictCategroryTable:(NSDictionary *)dict{ 
    UITableViewCell *myCell = (UITableViewCell *)[categoriesAndFunctionsTableView cellForRowAtIndexPath:[dict objectForKey:@"indexPath"]]; 
    UIButton *myBtn = (CustomUIButton *)[myCell viewWithTag:[[dict objectForKey:@"tag"] intValue]]; 
    if ([dict objectForKey:@"imageValue"]) { 
     [myBtn setImage:[dict objectForKey:@"imageValue"] forState:UIControlStateNormal]; 
    } 
} 

我已经张贴了我的所有代码这可能与此错误有关。请任何人建议我如何解决此问题。

在此先感谢!

回答

1

所以我猜想发生的是你是running out of Mach ports。它看起来像你正在为表中的每个单元格启动一个线程,然后他们都试图安排任务在主runloop上运行时完成。这会给你的系统带来压力。

我会为每个图像创建一个NSOperation,并将它们安排在同一个NSOperationQueue中。运行时将使用调整到特定系统的线程池来运行所有操作。

对于这样一个简单的事情,你也可以像奥斯卡所说的那样使用GCD,但是我最近在Apple列表上看到NSOperationQueue是首选,因为它的级别更高。它为您提供更多选项来控制后台任务发生的情况。

+0

非常感谢你的答案。我尝试过使用NSOperationQueue,现在应用程序不是没有冻结,但没有图像在我的按钮上。对象:catPassdict];我们可以通过下面的例子来说明如何使用NSInvocationOperation。 \t \t \t \t \t \t \t \t \t \t \t \t [functionOperationQueue addOperation:invOperation]; \t \t \t \t \t \t \t [invOperation release]; functionOperationQueue是我的全局变量。请你看看我做错了什么。 – Gypsa 2012-03-05 05:44:00

+0

@Gypsa:当你得到图像时,你可能需要强制表格视图重新显示。 – JeremyP 2012-03-05 10:36:47

+0

一旦表格滚动,我看到现在显示的SmallImageForFunctionsApps没有被调用。它是当滚动或滚动操作后没有添加到队列中。 – Gypsa 2012-03-06 04:04:39

2

我会建议不要使用线程,并将您的代码移动到GCD,看起来像你想使用的是一个串行队列。

+0

最近在Apple列表中,有人说您应该使用可用的最高级API。在这种情况下,这将是'NSOperationQueue'。 – JeremyP 2012-03-02 13:59:10

+0

我个人比较喜欢GCD到NSOperationQueue。 – Wevah 2012-03-02 14:02:52

+0

@ Wevah:我不是说GCD已被弃用或者其他任何东西,这正是我在Apple列表上读到的。就我个人而言,我更喜欢NSOperationQueue,因为它是Objective-C,但在这种情况下,所有后台处理都在一个函数中,将一个块粘在GCD队列上并不成问题。 – JeremyP 2012-03-02 14:14:28