Search code examples
iosobjective-cnsthread

while loop can't exit without NSLog


I am trying to create a login page that displays a waiting page while attempting. it has an UIActivityIndicatorView runs on main thread and another thread doing the connection. The code works fine when I uncomment NSLog, but it keeps running when I comment it out. Can anyone explain to me why it doesn't exist the while loop when there is no NSLog? it is a bit complicated. I have a control class that prepare the websocket command and fires it if and only if the websocket is successfully connected.

The action flow is like this:

LoginButton is clicked -> rootView calls [_spinner startAnimating]; -> attempting connecting to websocket -> send log in command when successfully connected.

rootView has to animate the spinner and wait for the response.

  [_spinner startAnimating];
  [NSThread detachNewThreadSelector:@selector(attampingWS) toTarget:self withObject:nil];


  - (void) attampingWS {
     while ([connection isAttamptingWS] && ![connection isConnectedToWebSocket]) {
        /** waiting until it's done **/
        //      NSLog(@"?");
     }
     if ([connection isConnectedToWebSocket]) {
           [self proceedLogin];
           [_spinner performSelectorOnMainThread:@selector(stopAnimating) withObject:nil waitUntilDone:NO];
     }
  }

in connection class:

  @property(nonatomic) NSTimer *attampConnectionTimeOut;
  @property(nonatomic) NSTimer *attampConnection;
  @property BOOL isConnectedToWebSocket;

  - (BOOL) isAttamptingWS {
     return [_attampConnection isValid];
  }

  - (BOOL) isWaitingForResponse {
     return [_waitingForResponse isValid];
  }
  /** this method is redirected from websocket by using delegation **/ 
  - (void)dbConnectionDidConnected:(websocket *)connection {
     [self _terminateAttamptingConnection];
     [self setIsConnectedToWebSocket:TRUE];
  }

Solution

  • Can anyone explain to me why it doesn't exit the while loop when there is no NSLog?

    Your code (invisibly) uses the main thread's run loop to process connection and timer callbacks. Those callbacks control the connection object's state and, as a result, the loop condition.

    When removing the NSLog call the status cannot change as the main thread is blocked and the runloop cannot process its sources.

    When inserting the call again, NSLog's implementation polls the runloop (maybe to communicate with the asl server). Within the call to NSLog the run loop can dispatch delayed actions, timers or connection callbacks, as dbConnectionDidConnected:. In this method the loop condition is becomes false and the loop exits as soon as the call to NSLog returns.