Razvan
Razvan

Reputation: 4122

GCD Dispatch - send notification when other method is called

I'm using a GCD dispatch queue to generate some reports when the view controller is instantiated - reports that the user will be able to share - so I have an action button with an UIActionSheet.

My question is this: since I generate the reports on a dispatch queue when ViewController loads - how can I send a notification to the action button method (other method) from dispatch queue - that has finished or not - if the user decides to press that button as soon as the ViewController loads ?

Right now, I'm using a BOOLEAN flag on the main thread which switches itself when dispatch queue has finished and I put a condition on the action button that disables the button if queue hasn't finished. But this is not OK... since it can make the user believe that is something wrong.

I want to let the user press the action button, show the action sheet, let the user press what sharing action he/she chooses and if the queue hasn't finished yet, wait until the queue has finished without blocking the UI and then show the MailComposer for example.

P.S. I've tried this with a while loop in the action button method with the BOOL flag mentioned above, but the UI blocks and remains in that state forever.

This is the code to generate the reports on viewDidLoad:

    dispatch_queue_t emailqueue;

    emailqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);

    dispatch_async(emailqueue, ^{
        [reportGenerator generate_Email_Report];
        [reportGenerator generate_PDF_Report];
        dispatch_async(dispatch_get_main_queue(), ^{done = YES;});});

    dispatch_release(emailqueue);

And this is what I use on the Action Button:

    if (done == YES)
    {
    if (version >= 6.0)
    {
        //UIActivityViewController *shareController = [[UIActivityViewController alloc] initWithActivityItems:@[ profileName.text,profileImage] applicationActivities:nil];
        //[self presentViewController:shareController animated:YES completion:nil];
    }

    else
    {
        UIActionSheet *selectSource = [[UIActionSheet alloc]
                                       initWithTitle:nil
                                       delegate:self
                                       cancelButtonTitle:@"Cancel"
                                       destructiveButtonTitle:nil
                                       otherButtonTitles:@"Send Report To Mail",
                                       @"Send Report PDF To Mail", nil];
        selectSource.delegate = self;
        [selectSource showInView:self.view];
        selectSource.actionSheetStyle = UIActionSheetStyleBlackTranslucent;
    }
    }

Upvotes: 0

Views: 691

Answers (1)

user1078170
user1078170

Reputation:

I would use an NSNotification. You can add whatever class you like as an observer for that notification and modify whatever behavior you like in response to it. Just make sure that you post it on the main thread. So, if your processing is running in the background, then whenever it is complete, post your notification to the main queue to let the user do what you want.

Just saw your edits. If you want to not disable the button, you can just show your next VC with a UIActivityIndicatorView and when you receive your notification, remove the spinner, load the view and let the user do whatever.

   [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(handleThisNotification:)
    name:WhateverYouDecideToNameYourNotification
object:nil];

    -(void)handleThisNotification {
        //load your view controller and remove the spinner
    }

Upvotes: 1

Related Questions