Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

performSelector:withObject:afterDelay: not making call

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. =/

like image 301
Padin215 Avatar asked Jan 05 '12 16:01

Padin215


3 Answers

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

like image 182
hatunike Avatar answered Nov 15 '22 05:11

hatunike


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];
}
like image 38
rishi Avatar answered Nov 15 '22 05:11

rishi


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).

like image 1
DBD Avatar answered Nov 15 '22 06:11

DBD