performSelector:withObject:afterDelay: not making call
Solution 1
Try using:
-(void) select {
[self changeButtonNames];
[self drawMap];
[self performSelectorOnMainThread:@selector(showActionSheet) withObject:nil waitUntilDone:YES];
}
-performSelector:withObject:afterDelay:
schedules a timer on the same thread to call the selector after the passed delay.
Maybe this will work for you:
-(void) select {
[self changeButtonNames];
[self drawMap];
[self performSelectorOnMainThread:@selector(someA) withObject:nil waitUntilDone:YES];
}
-(void)someA {
[self performSelector:@selector(showActionSheet) withObject:nil afterDelay:2];
}
Solution 2
I ran into this same issue, and by necessity I solve it slightly different from the accepted answer. Notice I wanted my delay and selectors to be variables? Using a block allows me to stay within my current method.
dispatch_async(dispatch_get_main_queue(), ^{
[self performSelector:loopSelector withObject:nil afterDelay:cycleTime];
});
By the way, this is definitely a threading issue. The documentation for performSelector:withObject:afterDelay: states that this will be performed on the current thread after the delay, but sometimes that thread's run loop is no longer active.
A more detailed discussion on the subject can be found here
Solution 3
Does your class still exist in memory?
If your class goes away before the performSelector fires, do you wind up sending the message to nil
(which would cause nothing to occur).
You could test this by dropping an NSLog
into your dealloc()
You mentioned threads. If your performSelector isn't called from the MainThread it could cause issues (UI things should be done on the main thread).
Related videos on Youtube
Padin215
Updated on June 04, 2022Comments
-
Padin215 almost 2 years
in a method, i want to call a method after n seconds:
self.toolBarState = [NSNumber numberWithInt:1]; [self changeButtonNames]; [self drawMap]; [self performSelector:@selector(showActionSheet) withObject:nil afterDelay:2];
i want to show the action sheet 2 seconds after drawMap is complete. when i use this performSelector, it never makes the call.
if i just put [self showActionSheet];, it works just fine. is there reason why the performSelector is not making the call?
EDIT: in another part of my code, i make the same call and it works:
HUD = [[MBProgressHUD alloc] initWithView:self.view]; [self.view addSubview:HUD]; HUD.delegate = (id) self; [HUD showWhileExecuting:@selector(drawMap) onTarget:self withObject:nil animated:YES]; [self performSelector:@selector(showActionSheet) withObject:nil afterDelay:6];
here, the showActionSheet gets called 6 seconds after drawMap has completed. i'm guessing there is something going on with the threads that i don't understand yet...
EDIT2:
-(void)showActionSheet { InspectAppDelegate *dataCenter = (InspectAppDelegate *) [[UIApplication sharedApplication] delegate]; if (dataCenter.fieldIDToPass == nil) { UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Selected Boundary Options" delegate:(id) self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Analyze a Field",@"Retrieve Saved Analysi", @"Geotag Photos", @"Refresh the map",nil]; actionSheet.tag = 0; [actionSheet showInView:self.view]; } else { UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Selected Boundary Options" delegate:(id) self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Analyze a Field",@"Retrieve Saved Analysi", @"Geotag Photos", @"Attribute the Field", @"Refresh the map",nil]; actionSheet.tag = 0; [actionSheet showInView:self.view]; } }
EDIT3:
ok, so the progress of method calls is:
-(void) foundDoubleTap:(UITapGestureRecognizer *) recognizer { [HUD showWhileExecuting:@selector(select) onTarget:self withObject:nil animated:YES]; } -(void) select { [self changeButtonNames]; [self drawMap]; [self performSelector:@selector(showActionSheet) withObject:nil afterDelay:2]; }
showActionSheet never gets called. like i said, i'm pretty sure its a threading issue. if call it with [self showActionSheet], it will run. =/
-
Padin215 over 12 yearsthis does work, the method gets called but there is no delay which is what i'm trying to do. i want showActionSheet to wait n seconds after drawMap is complete (i'm making a change to the view and want the user to see the change before the action sheet is brought up).
-
rishi over 12 yearsYes.there is no delay on main thread methods, you can try with edited part above
-
Padin215 over 12 yearsha, that works perfectly! think you could explain why this works? i'm guessing it has something to do with the threads, where this is getting process back onto the main thread which does get killed?
-
rishi over 12 yearsshowWhileExecuting works on a new thread, so from there before calling any other selector you need to move to main thread. That is main logic. For more information you can check - developer.apple.com/library/mac/#documentation/Cocoa/Reference/…
-
Padin215 over 12 yearsawesome, thanks for the info. i added in some NSLog(@"%@", [NSThread currentThread]) and ya, as soon as it goes to -(void)select its a new thread. with the fix, when it gets to -(void)showActionSheet its back on the main thread.
-
Padin215 about 11 yearsYep, I recently updated the MBProgressHUD library and in their how-to, they suggest getting the main thread and running the methods just like this. I've switch to doing it this way as well.
-
jab about 10 yearsThe OP needs the main thread to show an action sheet. My problem was a little different, but this was still basically a good solution. I used
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
rather than run on the main queue.