I followed this answer and this answer which are both from Apple engineers.
The first one said to create multiple concurrent NISessions:
All NISessions are peer-to-peer and as a result, creating multiple NISession objects is necessary to have multiple concurrent sessions.
One approach is to create a dictionary between an identifier for the peer (i.e. a user identifier provided by your app MyAppUserID) and the NISession objects while also keeping track of the NIDiscoveryToken for each peer identifier:
And the second answer said to perform interactions with multiple iPhones:var sessions = [MyAppUserID: NISession]()
var peerTokensMapping = [NIDiscoveryToken: MyAppUserID]()
Create an NISession for each peer you would like to interact with. For example, if you are interacting with two peers, create 2 * NISession objects.
Each NISession will have a unique NIDiscoveryToken associated with it. Share discovery token #1 with peer #1, and share discovery token #2 with peer #2.
The problem is when sending out a NIDiscoveryToken via NWConnection, I can't find a way to link to the NISession from the sent out data to the token that is received from the incoming data after I initialize a NINearbyPeerConfiguration object:When you receive discovery tokens from peers #1 and #2, create 2 * NINearbyPeerConfiguration objects and use them to run sessions #1 and #2, respectively.
eg.
User object which is sent and received when other devices are discovered
Code Block class User: NSObject, NSSecureCoding { var uid: String? var peerToken: NIDiscoveryToken? = nil init(uid: String, peerToken: NIDiscoveryToken) {...} // ... encoder for uid and peerToken // ... decoder for uid and peerToken }
Send current user's NIDiscoveryToken data via NWBrowser and NWConnection and save it to the
peerTokensMapping dictionary and save the session to the sessionsArr
Code Block let currentUserId = "qwerty" var sessionsArr = [NISession]() var sessions = [String: NISession]() var peerTokensMapping = [NIDiscoveryToken: String]() func sendDataWhenNewDeviceIsDiscovered() { let session = NISession() session.delegate = self guard let myToken = session.discoveryToken else { return } let user = User(uid: currentUserId, peerToken: myToken) guard let outgoingData = try? NSKeyedArchiver.archivedData(withRootObject: user, requiringSecureCoding: true) else { return } let message = NWProtocolWebSocket.Metadata(opcode: .text) let context = NWConnection.ContentContext(identifier: "send", metadata: [message]) connection.send(content: outgoingData, contentContext: context, isComplete: true, completion: .contentProcessed({ [weak self](error) in if let error = error { return } self?.sessionsArr.append(session) self?.peerTokensMapping[myToken] = self!.currentUserId print("Successfully Sent") })) }
Receive other user's NIDiscoveryToken data via NWListener and NWConnection.
Code Block connection.receive(minimumIncompleteLength: 1, maximumLength: 65535) { [weak self](data, context, isComplete, error) in if let err = error { return } if let data = data, !data.isEmpty { self?.decodeReceived(data) } } func decodeReceived(_ data: Data) { guard let incomingData = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? User else { return } guard let uid = incomingData.uid, let peerToken = incomingData.peerToken else { return } let config = NINearbyPeerConfiguration(peerToken: peerToken) /* not sure what to do here to get the session that was created when the data was sent out */ for (key,_) in peerTokensMapping { if key.??? == peerToken.??? { session.run(config) self.sessions[currentUserId] = session break } } /* or try this but this is the other user's peerToken so this will never work */ for session in self.sessionsArr { if session.discoveryToken ?? "" == peerToken { session.run(config) self.sessions[currentUserId] = session break } } }
Once the NINearbyPeerConfiguration is initialized how do I connect the incoming peerToken with the correct one that was sent out above that is currently inside the peerTokensMapping dict or the sessionsArr so that I can
get the session and call session.run(config)