简体   繁体   中英

Detect end of performSelectorInBackground:withObject:

I have an asynchronous server request in my iOS app:

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

How can I detect the end of this operation?

Put a call at the end of the doSomething method?!

- (void)doSomething {
    // Thread starts here

    // Do something

    // Thread ends here
    [self performSelectorOnMainThread:@selector(doSomethingDone) withObject:nil waitUntilDone:NO];
}

If you just want to know when it's finished (and don't want to pass much data back - at which point I would recommend a delegate) you could simply post a notification to the notification center.

[[NSNotificationCenter defaultCenter] postNotificationName:kYourFinishedNotificationName object:nil];

within your view controllers viewDidLoad method add:

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(yourNotificationListenerMethod:)
                                                 name:kYourFinishedNotificationName
                                               object:nil];

and within dealloc, add:

[[NSNotificationCenter defaultCenter] removeObserver:self];

I have a general background handler I created that solves this problem. Only the first method is public so it can be used throughout. Note that all parameters are required.

+(void) Run: (SEL)sel inBackground: (id)target withState: (id)state withCompletion: (void(^)(id state))completionHandler       // public
{
    [(id)self performSelectorInBackground: @selector(RunSelector:) withObject: @[target, NSStringFromSelector(sel), state, completionHandler]];
}

+(void) RunSelector: (NSArray*)args
{
    id target = [args objectAtIndex: 0];
    SEL sel = NSSelectorFromString([args objectAtIndex: 1]);
    id state = [args objectAtIndex: 2];
    void (^completionHandler)(id state) = [args objectAtIndex: 3];
    [target performSelector: sel withObject: state];
    [(id)self performSelectorOnMainThread: @selector(RunCompletion:) withObject: @[completionHandler, state] waitUntilDone: true];
}

+(void) RunCompletion: (NSArray*)args
{
    void (^completionHandler)(id state) = [args objectAtIndex: 0];
    id state = [args objectAtIndex: 1];
    completionHandler(state);
}

Here's an example of how it's called:

NSMutableDictionary* dic = [[NSMutableDictionary alloc] init];
__block BOOL done = false;
[Utility Run: @selector(RunSomething:) inBackground: self withState: dic withCompletion:^(id state) {
        done = true;
    }];

You may want to have your doSomething selector post back when it has completed itself. What happens on performSelectorInBackground is internal to the API and if you want more control you may want to use performSelector:onThread:withObject:waitUntilDone: and periodically check the isFinished on the thread passed. I am sure you are more concerned about doSomething finishing than the actual thread though so just post back from there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM