Detect end of performSelectorInBackground:withObje

2019-04-09 17:38发布

问题:

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?

回答1:

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];
}


回答2:

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];


回答3:

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.



回答4:

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;
    }];