title: Calling close() in iOS on a bluetooth connection causes data to be lost
body: <p>We have an application that is sending data over Bluetooth then closes the connection.</p>
  
  <p>The root problem is calling close() before all the data has been sent over Bluetooth causes iOS to not always send all the data.   </p>
  
  <p>This looks to be an iOS issue.   Each write is done successfully at the lowest NSOutputStream level, (We've even added code to catch the event generated after each write that says more space is available) but it appears iOS is somehow buffering things internally and out of our control.  When the final close() is called, depending on the timing, iOS might discard pending data even though all the calls to write had returned success and the associate event of more space available was received.   I've been looking at Apple's documentation for EASessions and their associated streams, but haven't been able to find any way to determine if there is still pending data in flight internally within iOS.</p>
  
  <p>So far, the rough hack of adding a call to sleep() for some arbitrary number of seconds before the close() will eliminate the problem, but the delay needed is really dependent on how much data was sent and how quickly the underlying Bluetooth transfer takes, so there's not an easy way to know before-hand how many seconds the delay needs to be.</p>
  
  <p>We have also needed to add a delay after consecutive writes. Using a value of 20 mS will fail while having a value of 200mS will succeed, but results in slow communications.    </p>
  
  <pre><code>(NSInteger) write:(NSData *)data error:(NSError **)error {
  NSOutputStream *outputStream = [[Test_EADSessionController sharedController] getOutputStream];
  
  if(m_isConnected == NO) {
                              [TestError setError:error withErrorCode:Test_ERROR_NO_CONNECTION];
                              return -1;
              }
  
              const void* dataAsBytes = [data bytes];
              NSInteger len = [data length];
              NSInteger bytesWritten = 0;
              while(bytesWritten &lt;len){
      int maxTimeToWaitForSpaceAvailable = 2000 * 1000;
  
      while([outputStream hasSpaceAvailable] == NO &amp;&amp; maxTimeToWaitForSpaceAvailable &gt; 0) {
          usleep(100 * 1000);
          maxTimeToWaitForSpaceAvailable -= 100 * 1000;
      }
  
      NSInteger bytesToWrite = MIN(1024, len - bytesWritten);
      NSInteger tmp = [outputStream write:dataAsBytes + bytesWritten maxLength:bytesToWrite];
  
      usleep((int)([self timeToWaitAfterWriteInMilliseconds] * 1000));
  
                              if(tmp &lt;= 0){
                                              bytesWritten = -1;
                                              [TestError setError:error withErrorCode:TEST_ERROR_WRITE_FAILURE];
                                              break;
                              }
                              bytesWritten += tmp;
              }
  usleep((int)([self timeToWaitAfterWriteInMilliseconds] * 1000));
              return bytesWritten;
  </code></pre>
  
  <p>}</p>