Multipeer Connectivity: data not transferred in a stream

Hi. I am using Swift's Multipeer Connectivity framework to try to pass data from SKScene:


My AppDelegate class:


class AppDelegate: UIResponder, UIApplicationDelegate
    {
        /// Object to class ConnectionManager
        var connectionManager: ConnectionManager!
   
        var window: UIWindow?
   
   
        func application(_ application: UIApplication,
                         didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
        {
            // Override point for customization after application launch
            connectionManager = ConnectionManager()
            return true
        }
    }


This is a subclass of SKScene:



class GameScene: SKScene
    {
        /// Object of appDelegate
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
   
        override func touchesEnded(_ touches: Set, with event: UIEvent?)
        {
            for touch in touches
            {
                let location = touch.location(in: self)
               
                if let card = atPoint(location) as? Card
                {
                    // Code to manipulate SKNodes
                }
               
                print("TOUCHES ENDED")
                // Send Data to Peers
                appDelegate.connectionManager.sendDataToPeer()
            }
        }
       
    }


This is the class that manages MPC connection



class ConnectionManager : NSObject, MCSessionDelegate, MCNearbyServiceBrowserDelegate, MCNearbyServiceAdvertiserDelegate, StreamDelegate
    {


        var delegate: ConnectionManagerDelegate?
   
        override init()
        {
            super.init()
           
            // Initialize peerID
            peer = MCPeerID(displayName: UIDevice.current.name)
           
            // Session object
            session = MCSession(peer: peer, securityIdentity: nil, encryptionPreference: MCEncryptionPreference.optional)
            session.delegate = self
           
            // Browser object
            browser = MCNearbyServiceBrowser(peer: peer, serviceType: CONNECTION_SERVICE_TYPE)
            browser.delegate = self
           
            // Advertiser object
            advertiser = MCNearbyServiceAdvertiser(peer: peer,
                                                   discoveryInfo: nil,
                                                   serviceType: CONNECTION_SERVICE_TYPE)
            advertiser.delegate = self
        }
   
   
        /** State of the session */
        func session(_ session: MCSession,
                     peer peerID: MCPeerID,
                     didChange state: MCSessionState)
        {
            switch state
            {
            case MCSessionState.connected:
                print("Connected to session: \(session)")
                delegate?.connectedWithPeer(peerID: peerID)
                // Start Stream
                startSession(peer: peerID)
   
            case MCSessionState.connecting:
                print("Connecting to session: \(session)")
               
            default:
                print("Did not connect to session: \(session)")
                stopSession()
            }
        }
   
   
        /** Starting session */
        func startSession(peer peerID: MCPeerID)
        {
            print("STARTING STREAM IN SESSION...")
            do
            {
                try outputStream = self.session.startStream(withName: "stream", toPeer: peerID)
   
                print("OUTPUT STREAM IN STARTSESSION? ",outputStream)
               
                if let outputStream = outputStream
                {
                    outputStream.delegate = self
                    outputStream.schedule(in: RunLoop.main, forMode:RunLoopMode.defaultRunLoopMode)
                    outputStream.open()
                    print("STREAM WITH PEER OPENED: ",peerID)
                }
            }
            catch let error
            {
                print("ERROR STARTING STREAM IN SESSION: \(error)")
            }
        }
   
        /** Sending data to peer */
        func sendDataToPeer()
        {
           
            if session.connectedPeers.count > 0
            {
                print("SEND DATA TO PEER: MORE THAN ONE PEER")
               
                let message = "This is a string test"
                let data = NSKeyedArchiver.archivedData(withRootObject: message)
               
                if let outputStream = outputStream
                {
                    _ = data.withUnsafeBytes { outputStream.write($0, maxLength: data.count) }
                
                    print("OUTPUTSTREAM FROM SENDING DATA TO PEER")
                }
             }
         }
   
        /** Receiving stream data */
        func session(_ session: MCSession,
                     didReceive stream: InputStream,
                     withName streamName: String,
                     fromPeer peerID: MCPeerID)
        {
           
            if streamName == "stream"
            {
                stream.delegate = self
                stream.schedule(in: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
                stream.open()
               
                print("STREAM OPENED: ",streamName)
            }
        }
   
   
        func stream(aStream: Stream, handleEvent eventCode: Stream.Event)
        {
            switch(eventCode)
            {
                case Stream.Event.hasBytesAvailable:
                print("--STREAM EVENT HAS BYTES--")
                let input = aStream as! InputStream
                var buffer = [UInt8](repeating: 0, count: 1024) //allocate a buffer. The size of the buffer will depended on the size of the data you are sending.
                let numberBytes = input.read(&buffer, maxLength:1024)
                let dataString = NSData(bytes: &buffer, length: numberBytes)
                let message = NSKeyedUnarchiver.unarchiveObject(with: dataString as Data) as! String //deserializing the NSData
                print("STREAM: ",message)

   
                case Stream.Event.hasSpaceAvailable:
                    print("--STREAM EVENT HAS SPACE AVAILABLE--")
                    break
   
                default:
                    print("--STREAM EVENT DEFAULT--")
                    break
            }
        }
    }


So, I have no issues with connection, browsing or advertising. I see that I am connected to the session, then I see: STREAM WITH PEER OPENED... STREAM OPENED. When I manipulate with the SKNodes, I also see: "OUTPUTSTREAM FROM SENDING DATA TO PEER". So, data is being sent and the InputStream is supposedly opened.


However, I do not see anything happening in stream(aStream:, handleEvent eventCode:). Looks like there is no data transferred in the stream.


I would appreciate if someone could help. Thanks!

Accepted Reply

The right signature of StreamDelegate method is:

func stream(_ aStream: Stream, handle eventCode: Stream.Event)

stream(_:handle:)


I haven't checked other parts of your code, but, at least, you need to change the method header to the right one.

Replies

The right signature of StreamDelegate method is:

func stream(_ aStream: Stream, handle eventCode: Stream.Event)

stream(_:handle:)


I haven't checked other parts of your code, but, at least, you need to change the method header to the right one.

That was it! Spent three days on this. :-) Thank you so much!


P.S. If you happen to see other flaws in the code, I will be happy to hear it!


Cheers.