سؤال

Pretty generic question, is there a way to call a method I have every so often with the application without blocking the UI load?

هل كانت مفيدة؟

المحلول

You can use Grand Central Dispatch for this:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, kNilOptions), ^{
    // Call your method.
});

نصائح أخرى

You definitely want to use Grand Central Dispatch to do this, but I'd just like to point out that GCD has a method build just for this kind of thing. dispatch_apply() executes its block a specified number of times on a queue of your choosing, of course, tracking which iteration you're on along the way. Here's an example:

size_t iterations = 10;

dispatch_queue_t queue = dispatch_queue_create("com.my.queue", DISPATCH_QUEUE_SERIAL);

dispatch_apply(iterations, queue, ^(size_t i) {
    NSLog(@"%zu",i);// Off the main thread.

    dispatch_async(dispatch_get_main_queue(), ^{
        // Go back to main queue for UI updates and such
    });
});

You could use:

[self performSelectorInBackground:@selector(aMethod) withObject:nil];

for a method with no parameters. Or something like

[self performSelectorInBackground:@selector(otherMethodWithString:andData:) withObjects:string, data, nil];

if you have parameters.

Here's another example, explaining how to execute background queues and iterate with the user inside it.

- (void)method
{
    // start a background proccess that will not block the UI
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        for (int i = 0; i < 1000000; i++) {

            if (i == 999) {

                // Need to iterate with interface elements when inside a background thread.
                dispatch_async(dispatch_get_main_queue(), ^{
                    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Found" message:@"Found your number" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                    [alertView show];
                });
            }

            NSLog(@"Count: %d",i);
        }

    });
}

Using GCD is definitely a good way to go, as others have noted.

Alternatively, if you want the operation to be cancelable (e.g. loading a web resource), you might consider subclassing NSOperation and checking for isCancelled.

(AFNetworking actually does this (e.g. AFHTTPRequestOperationManager) in making / managing web requests.)

Checkout the Apple docs on NSOperation and also this tutorial on Ray Wenderlich's site for more details on NSOperations.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top