0

I am using GCD in my app to fetch lot of images and data in the background queue and when I present uiimagepickercontroller it takes more time to show the camera preview. After googling around, I found that many have faced this issue with iOS 7 and here is one more post that made some sense to me. (iOS 7 UIImagePickerController Camera No Image). The solution was to stop the background threads and then present the picker controller. But I am really stumped and don't know how to stop or pause the background threads, present the picker controller and then resume/start the background thread. Can someone please help me with this.

Here is how I am doing my background fetching of images and data in my networking class (like everyone else). My serial queue is initialized like this.

sharedInstance.serialQueue = dispatch_queue_create("user-detail-queue", DISPATCH_QUEUE_CONCURRENT);

And the code to fetch things in the background is like this.

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        NSString *myUserID = [JNKeychain loadValueForKey:@"userID"];
        NSString *sessionToken = [JNKeychain loadValueForKey:@"sessionToken"];
        if(sessionToken && myUserID)
        {
            dispatch_async([BGNetworkAPI sharedInstance].serialQueue, ^{
                id object = [[BGNetworkAPI sharedInstance].userCache objectForKey:myUserID];
                if(object)
                {
                    NSDictionary *cachedResponseDictionary = (NSDictionary *)object;
                    BGUser *user = [BGUser createUserWithResponseDictionary:cachedResponseDictionary];
                    if(block)
                    {
                        block(user, nil);
                    }
                }
                else
                {
                  [[BGUserManagementClient sharedClient] fetchUserDetailsWithUserId:myUserID withSessionToken:sessionToken withSuccessBlock:^(AFHTTPRequestOperation *operation, id responseObject)
                 {
                     //NSLog(@"The response object of my user object is %@",responseObject);
                     [[BGNetworkAPI sharedInstance].userCache setObject:responseObject forKey:myUserID];
                     NSDictionary *responseDictionary = (NSDictionary *)responseObject;
                     BGUser *user = [BGUser createUserWithResponseDictionary:responseDictionary];
                     if(block)
                     {
                         block(user,nil);
                     }
                 } failure:^(AFHTTPRequestOperation *operation, NSError *error)
                 {
                     NSLog(@"The error while fetching the user details is %@", operation.responseObject);
                     if(block)
                     {
                         block(nil, error);
                     }
                 }];
                }
             }
        });
Community
  • 1
  • 1
jeevangs
  • 306
  • 5
  • 20
  • I used `UIImagePickerController` in my app recently, and there is nothing done in a background thread. Yet, the image picker still takes a lot of time to be loaded, but only the first time. – Sunder Apr 18 '14 at 15:23

2 Answers2

0

With the code above you are not doing the fetching in the backgroud as dispatch_get_main_queue()gives you the queue the interface is running on. To perform a background fetch you have to open another queue with dispatch_queue_create("image_queue", NULL).

When the backgroud fetch is finished and you want to do something with the UI you have to do this in the main queue.

dispatch_async(dispatch_get_main_queue(),^{
  if(block) {
    block(user,nil)
  }
});
HackingOtter
  • 134
  • 6
  • Does ist work now? If not the problem could be the second dispatch with `[BGNetworkAPI sharedInstance].serialQueue` – HackingOtter Apr 18 '14 at 15:40
  • Your pointer to dispatch_get_main_queue() solved my problem. Thanks a lot!I had to send all my completion blocks to the main queue and in that way, I have the main queue handle and when I present the image controller now, it works properly. – jeevangs Apr 18 '14 at 15:50
  • So the code where I am returning if(block){block(user,nil)}, that part I had put it inside dispatch_async(dispatch_get_main_queue(),{if(block){block(user,nil)}}); – jeevangs Apr 18 '14 at 16:13
0

After playing around with the code, I figured out the problem. In all the places where I am doing background fetch, I was sending the completion block just like that. When I changed the returning of the completion block in the main block, it started to work properly. Thanks a lot to @HackingOther to point out my mistake.

jeevangs
  • 306
  • 5
  • 20