使用GCD但我的应用程序在从服务器加载图像时仍然冻结

时间:2013-07-22 20:19:36

标签: ios objective-c sql-server multithreading

每次用户点击刷新按钮时,我实际上是从服务器加载图像。但是,这个加载机制会冻结主线程,所以我决定尝试使用GCD在不同的线程中加载图像。我看过教程,似乎我正确地设置它,但我仍然遇到同样的问题。

我的代码:

-(IBAction)refreshButton:(id)sender{

    dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);

    dispatch_async(myQueue, ^{
        [[API sharedInstance] commandWithParams:[NSMutableDictionary dictionaryWithObjectsAndKeys:
                                                 @"stream",@"command",@"0",@"IdImage",_contentFilter,@"contentFilter",
                                                 nil]
                                   onCompletion:^(NSDictionary *json){
                                       NSMutableArray *tempArray = [json objectForKey:@"result"];
                                       NSMutableArray *tempDataArray = [[NSMutableArray alloc] initWithCapacity:[_imagesTemporaryHolder count]];
                                       NSLog(@"loaded temporary image holder");
                                       for (int i=0;i<[_images count];i++) {
                                           NSLog(@" populating _imagesData");
                                           NSString *imageID = [[tempArray objectAtIndex:i] objectForKey:@"IdImage"];
                                           NSString *imageURL = [NSString stringWithFormat:@"http://swiphtapp.com/Swipht/upload/%@.jpg",imageID];
                                           NSData *tempImageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:imageURL]];
                                           [tempDataArray insertObject:tempImageData atIndex:i];
                                        }


                                   }];

        dispatch_async(dispatch_get_main_queue(), ^{
            // Update the UI

        });
    });

}

难道我需要去API类并在那里进行更改吗?我顺便使用 AFNNETWORKING

非常感谢您的帮助!

更新1

看起来API的“onCompletion”块是导致问题的原因...我在NSLog(isMainThread)中检查了它,它返回YES意味着它在主线程中运行,尽管它不应该像我把它封装在GCD中。关于如何解决这个问题的想法?

感谢非常感谢人们

@eric

API调用的完成块意味着在主线程上执行,因为它通常会根据收到的数据更新视图。尝试将GCD内容放在完成块中,而不是将整个内容封装在其中。在主线程上花了这么长时间,因为你从原始API调用返回的url中获取了NSData,这可能需要很长时间(相对而言)

基本上GCD需要在API调用的完成块中。

再次感谢!

1 个答案:

答案 0 :(得分:0)

我相信这是我们在最初发表的评论中得出的答案:

-(IBAction)refreshButton:(id)sender
{
    [[API sharedInstance] commandWithParams:[NSMutableDictionary dictionaryWithObjectsAndKeys:
                                             @"stream",@"command",@"0",@"IdImage",_contentFilter,@"contentFilter",
                                             nil]
                               onCompletion:^(NSDictionary *json){

                                   dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);

                                   dispatch_async(myQueue, ^{
                                       NSMutableArray *tempArray = [json objectForKey:@"result"];
                                       NSMutableArray *tempDataArray = [[NSMutableArray alloc] initWithCapacity:[_imagesTemporaryHolder count]];
                                       NSLog(@"loaded temporary image holder");
                                       for (int i=0;i<[_images count];i++) {
                                           NSLog(@" populating _imagesData");
                                           NSString *imageID = [[tempArray objectAtIndex:i] objectForKey:@"IdImage"];
                                           NSString *imageURL = [NSString stringWithFormat:@"http://swiphtapp.com/Swipht/upload/%@.jpg",imageID];
                                           NSData *tempImageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:imageURL]];
                                           [tempDataArray insertObject:tempImageData atIndex:i];
                                        }
                                       dispatch_async(dispatch_get_main_queue(), ^{
                                           // Update the UI

                                       });
                                   });
                               }];
}