Issue with sync request and calls to UI elements

Discussion in 'iOS Programming' started by nashyo, Dec 24, 2012.

  1. nashyo macrumors 6502

    nashyo

    Joined:
    Oct 1, 2010
    Location:
    Bristol
    #1
    Ok, so I found something weird and I have a workaround in place, but can somebody tell me where I'm going wrong here?

    As you can see below, the delegate callback has been removed, and a timer put in its place.

    *With a timer, the delegate callback works and the 'WebViewController' dismisses.

    *Without a timer, the delegate callback works but the call to the UI element fails i.e. the 'WebViewController' doesn't dismiss (Modal view controller).

    I suspect it's due to the fact that the sendSync method goes off on it's own thread for a while before it finishes. Right?

    Code:
    -(BOOL)verifyRequest:(NSURLRequest*)theRequest
    {
        [self showProgressHudInView:self.view withText:@"Verifying Priveledges."];
        NSHTTPURLResponse *response; NSError *error;
        if ([[theRequest.URL description] rangeOfString:@"ticket=ST"].location != NSNotFound)
        {
            [NSURLConnection sendSynchronousRequest:theRequest
                                  returningResponse:&response
                                              error:&error];
        }
        
        if ([response statusCode] == 403)
        {
            [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(fireDelegateForStoppingDueToInsufficientPrivileges) userInfo:nil repeats:NO];
            return NO;
            
    //        if ([self.delegate conformsToProtocol:@protocol(WebViewControllerDelegate)])
    //        {
    //            [self.delegate webViewController:self
    //                         wasStoppedForReason:@"This device is currently restricted to Administrators only. Please contact an administration for more information."];
    //        }
    //        return NO;
        }
        else if (error)
        {
    //        if ([self.delegate conformsToProtocol:@protocol(WebViewControllerDelegate)])
    //        {
    //            [self.delegate webViewControllerDidFailLoadCheck:self withError:error];
    //        }
    //        return NO;
            [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(fireDelegateForStoppingDueToFailureToCheckPriviledges) userInfo:nil repeats:NO];
            return NO;
        }
        return YES;
    }
    Code:
    -(void)fireDelegateForStoppingDueToInsufficientPrivileges
    {
        if ([self.delegate conformsToProtocol:@protocol(WebViewControllerDelegate)])
        {
            [self.delegate webViewController:self
                         wasStoppedForReason:@"This device is currently restricted to Administrators only. Please contact an administration for more information."];
        }
    }
    
    -(void)fireDelegateForStoppingDueToFailureToCheckPriviledges
    {
                if ([self.delegate conformsToProtocol:@protocol(WebViewControllerDelegate)])
                {
                    [self.delegate webViewControllerDidFailLoadCheck:self withError:nil];
                }
    }
    DELEGATE
    Code:
    -(void)webViewController:(WebViewController *)theController wasStoppedForReason:(NSString *)theReason
    {
        NSLog(@"Is Main thread: %i", [NSThread isMainThread]);
        if (self.progressHud) [self hideProgressHudView];
        [theController dismissViewControllerAnimated:NO completion:^{
            NSLog(@"Dismiss block called.");
            [[[UIAlertView alloc] initWithTitle:@"Insufficient Privileges"
                                        message:theReason
                                       delegate:nil
                              cancelButtonTitle:@"Dismiss"
                              otherButtonTitles:nil, nil] show];
        }];
    }


    ----------

    I have tested the following. These are facts.

    1)Does the object your dismissing have the same memory address, before and after presenting/dismissing? i.e. is it the same object?
    YES

    2)Is the parent losing it's child?
    NO

    3)Are you using a depracated method?
    NO

    4)Are you calling dismiss from the parent?
    YES
     
  2. CodeBreaker macrumors 6502

    Joined:
    Nov 5, 2010
    Location:
    Sea of Tranquility
    #2
    Are you presenting any other view controllers during this process?

    No. It runs on the current thread (the thread in which it is created) and does not return till the request loads. In other words, it hangs the thread it runs in.

    Also, do not use timers for a problem like this. You can use performSelector:withObject:afterDelay: or better, dispatch_after().

    The only other thing that I can think of is that the controller that you are dismissing is nil, somehow (the parent loses a reference of it). It works when you use a timer because timers retain their targets by default. So as long as you don't invalidate the timer and release it, the timer's target (i.e., your controller) is retained.

    Another simple solution will be that the controller dismiss itself instead of asking the delegate to do it.
     
  3. nashyo thread starter macrumors 6502

    nashyo

    Joined:
    Oct 1, 2010
    Location:
    Bristol
    #3
    No, I wasn't presenting any other view controllers at that time.

    I analysed the delegate before and after the view controller was presented and I found the same memory address for the object it was associated with. Thus, it didn't seem to lose it's delegate, and then regain a new one later.

    I couldn't find an answer for this strange behaviour, so I am now not confirming the request before the web view loads. We have found another approach that doesn't demand this check.

    I might let it go as an oddity.
     

Share This Page