title: Swift Multipeer Connectivity - InputStream receiving empty data
body: <p>I'm doing a multiplayer game based on the MPC framework for the data communication between the devices of the players (and spritekit for the game).</p>
  
  <p>The logic is that one of the device is the master, does all the game logic and calculations, and sends the positions of the various sprites to the slave devices that just have to update the sprites positions.</p>
  
  <p>The master opens streams between him and all the slaves and sends the various data through these streams. Data are stored in dictionaries of type (String, Any).</p>
  
  <p>The issue is twofold :</p>
  
  <ul>
  <li>little by little I see a difference between the number of time the master send data and the number of time a slave received data</li>
  <li>the more the master increase the number of data sent the more the slave receive empty/partial data</li>
  </ul>
  
  <p>I have put various checks and controls, I don't have errors thrown by the send or receive functions, just lost data or empty/partial data.</p>
  
  <p>Here is below some relevant parts of the code. Let me know if more is needed</p>
  
  <p>Thx</p>
  
  <p>J.</p>
  
  <p><strong>Stream initialization between master and slaves</strong></p>
  
  <p>Executed by the master</p>
  
  <pre><code>func InitMPCStream()
  {
      for Peer in Session.connectedPeers
      {
          if Peer.displayName != gMasterPeerName
          {
              let IndexPeer = gtListPlayerMulti.index(where: { $0.Name == Peer.displayName } )
  
              try! gtListPlayerMulti[IndexPeer!].Stream = Session.startStream(withName: "Stream " + Peer.displayName, toPeer: Peer)
  
              gtListPlayerMulti[IndexPeer!].Stream!.delegate = self
              gtListPlayerMulti[IndexPeer!].Stream!.schedule(in: RunLoop.main, forMode:RunLoopMode.defaultRunLoopMode)
              gtListPlayerMulti[IndexPeer!].Stream!.open()
          }
      }
  }
  </code></pre>
  
  <p>Executed by the slaves</p>
  
  <pre><code>func session(_ session: MCSession, didReceive InStream: InputStream, withName StreamName: String, fromPeer PeerID: MCPeerID)
  {
      InputStream = InStream
      InputStream.delegate = self
      InputStream.schedule(in: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
      InputStream.open()
  }
  </code></pre>
  
  <p><strong>Function that sends the data to the slaves</strong></p>
  
  <p>This function is executed on the master side in the update loop of the SKScene, several times per update, so very often.</p>
  
  <p>The logic is that for each update cycle several events occur (between 10 to 100). Each event generates a call to this function. The quantity of data sent is not very important : a dictionary of (String, Any) of 3 to 10 lines where Any can be a string, number (Int, CGFloat...) or bool.</p>
  
  <pre><code>func SendStreamData(IDPeer: Int = 0, DataToSend: Dictionary&lt;String, Any&gt;)
  {
      let DataConverted = NSKeyedArchiver.archivedData(withRootObject: DataToSend)
  
      if IDPeer == 0
      {
          for Peer in Session.connectedPeers
          {
              let IndexPeer = gtListPlayerMulti.index(where: { $0.Name == Peer.displayName } )
              if gtListPlayerMulti[IndexPeer!].Stream!.hasSpaceAvailable
              {
                  let bytesWritten = DataConverted.withUnsafeBytes { gtListPlayerMulti[IndexPeer!].Stream!.write($0, maxLength: DataConverted.count) }
                  if bytesWritten == -1 { print("Erreur send stream") } else { gSendingNumber = gSendingNumber + 1 }
              } else { print("No space in stream") }
          }
      }
      else
      {
          let IndexPeer = gtListPlayerMulti.index(where: { $0.ID == IDPeer } )
  
          let bytesWritten = DataConverted.withUnsafeBytes { gtListPlayerMulti[IndexPeer!].Stream!.write($0, maxLength: DataConverted.count) }
      }
  }
  </code></pre>
  
  <p><strong>Function called when data is received on the slave side</strong></p>
  
  <pre><code>func stream(_ aStream: Stream, handle eventCode: Stream.Event)
  {
      switch(eventCode)
      {
      case Stream.Event.hasBytesAvailable:
          gSendingNumber = gSendingNumber + 1
          let InputStream = aStream as! InputStream
          var Buffer = [UInt8](repeating: 0, count: 1024)
          let NumberBytes = InputStream.read(&amp;Buffer, maxLength:1024)
          let DataString = NSData(bytes: &amp;Buffer, length: NumberBytes)
          if let Message = NSKeyedUnarchiver.unarchiveObject(with: DataString as Data) as? [String:Any] //deserializing the NSData
          { ProcessMPCDataReceived(VCMain: self, PeerID: PeerID, RawData: DataString as Data) }
          else { print("Empty Data") }
  
      case Stream.Event.hasSpaceAvailable:
          break
  
      case Stream.Event.errorOccurred:
          print("ErrorOccurred: \(aStream.streamError?.localizedDescription)")
  
      default:
          break
      }
  }
  </code></pre>
  
  <p>The issue here is on the NSKeyedUnarchiver.unarchiveObject line which return nil because DataString does not conform to the expected dictionary</p>