Post

Replies

Boosts

Views

Activity

Reply to Combine multiple outgoing NISessions with multiple NINearbyPeerConfiguration objects when data is received using Bonjour
I couldn't add these because the Edit button disappeared. 1- For clarity sendDataWhenNewDeviceIsDiscovered() {...} will run every time a new device is discovered but there will only be 20 sessions at a time. This won't stop it from running but the incomingData will never be added if the sessions are at 20. 2- In place of: var sessions = [MyAppUserID: NISession]() I used: var sessions = [String: NISession]() The problem is because the current user's userId is always the key, it will only have one key the will write always over its value self.sessions[currentUserId] = session I wasn't sure what was supposed to happen here. Did you mean: var sessions = [NISession: MyAppUserID]() or var sessions = [NISession: String]()
Topic: App & System Services SubTopic: General Tags:
Dec ’20
Reply to NISessionDelegate -How to convert distance property into meters?
I got the answer from here: - https://github.com/fitomad/NearbyInteraction-Guide/blob/master/NearbyInteraction-Framework-Guide.md The distance is a Float type whose value is measured in meters: func session(_ session: NISession, didUpdate nearbyObjects: [NINearbyObject]) {		 		guard let object = nearbyObjects.first else { return }          		 		guard let distance = object.distance else { return }  		let meters = String(format: "%.2f m", distance) 		print("meters: ", meters) }
Topic: App & System Services SubTopic: General Tags:
Jan ’21
Reply to NWConnection endPoint info duplicated
@eskimo ok thanks for the answer. I'll start a new thread about the issue that you just identified. As far as this one, how do I know who is talking to who by using self inside the receive(_:) method? Once a sender sends a message, I used these for the receiver to identify the sender: let endPointDescription = connection.currentPath?.localEndpoint?.debugDescription ... encode then send let remoteEndPoint = connection.currentPath?.remoteEndpoint?.debugDescription ... encode then send // they both get sent together This works fine when detecting when either end is cut off, for example if Device_A is connected to Device_B, if Device_B goes to the background the connection is cut and Device_A immediately knows about it. I haven't had any problems even when using 3 devices and 2 simulators. They all will know that Device_B has left the building and respond accordingly.
Apr ’21
Reply to NWConnection -no Echo from connection.send(content: data, completion : .idempotent)
@eskimo Thanks for the reply. Here are the successful print statements: The Initial Send does not send a color, it just sends some data like a String message : print("Sent") // successful After the Initial Send sends the message and it is first received, I didn't add a print statement for a successful reception but the code inside Receive data and send Echo response is successful, specifically if let data = data, !data.isEmpty { // successful only once } Inside there, the data that is decoded, only has the String message from above, the color isn't sent yet so the colorData decoding is skipped. However once the String message is received, I send an echo with the colorData connection.send(content: colorData, ... { } Inside the completionHandler of the echo, this print statement always runs: print("Color data sent") // successful At that point the other device, the Receive Data receives nothing, there isn't a response whatsoever. Nothing prints, it's as if the connection got cut off after the first reception. I put breakpoints everywhere but none of them get hit.
Apr ’21
Reply to NWConnection -no Echo from connection.send(content: data, completion : .idempotent)
Yes, they both have the same exact code. Btw neither device receives the echo but they both receive that first message. Here is startOutgoingConnection, actually here is PeerConnection because it is 1 class that has 2 initializers, one for outgoing and one for incoming. I put break points everywhere but nada on that 2nd incoming message. protocol PeerConnectionDelegate: class {     func sendOutgoing(_ connection: NWConnection)     func receivedIncoming(_ connection: NWConnection) } class PeerConnection: Hashable {     static func == (lhs: PeerConnection, rhs: PeerConnection) - Bool {         return lhs.connection?.endpoint.debugDescription == rhs.connection?.endpoint.debugDescription     }     func hash(into hasher: inout Hasher) {         guard let connection = connection else { return }         hasher.combine(connection.endpoint.debugDescription)     }     weak var delegate: PeerConnectionDelegate?     public var connection: NWConnection? // Outgoing     init(endPoint: NWEndpoint, delegate: PeerConnectionDelegate) {         self.delegate = delegate         let tcpOptions = NWProtocolTCP.Options()         tcpOptions.enableKeepalive = true         tcpOptions.keepaliveIdle = 2         let parameters = NWParameters(tls: nil, tcp: tcpOptions)         parameters.includePeerToPeer = true         parameters.allowLocalEndpointReuse = true         connection = NWConnection(to: endPoint, using: parameters)         startOutgoingConnection()     } // Incoming     init(connection: NWConnection, delegate: PeerConnectionDelegate) {         self.delegate = delegate         self.connection = connection         startIncomingConnection()     }     func startIncomingConnection() {         guard let connection = connection else { return }         connection.stateUpdateHandler = { [weak self](nwConnectionState) in             switch nwConnectionState {             case .preparing: print("preparing")             case .setup: print("setting up")             case .waiting(let error): print("\(error.localizedDescription)")             case .ready:                 self?.delegate?.receivedIncoming(connection)             case .cancelled:                 connection.cancel() // remove incoming connection from an array that holds it/them and remove corresponding cell             case .failed(let error):                 connection.cancel()                 // remove incoming connection from an array that holds it/them and remove corresponding cell             default:break             }         }         connection.start(queue: .main)     }     func startOutgoingConnection() {         guard let connection = connection else { return }         connection.stateUpdateHandler = { [weak self](nwConnectionState) in             switch nwConnectionState {             case .preparing: print("preparing")             case .setup: print("setting up")             case .waiting(let error): print(error.localizedDescription)             case .ready:                 self?.delegate?.sendOutgoing(connection)             case .cancelled:                 connection.cancel() // remove outgoing connection from an array that holds it/them             case .failed(let error):                 connection.cancel() // remove outgoing connection from an array that holds it/them             default:break             }         }         connection.start(queue: .main)     } } The connection isn't failing on either end/device because once it is cancelled I remove data from both devices which never happens after they both send and receive messages from each other. For example Device_A sends its info to Device_B and vice versa. I have a cell that shows the connection info String data like connection.endpoint.debugDescription and the uid from the opposite device. Once either device goes to the background and the connection is cancelled then both devices remove the corresponding cell. If the connection was cancelled after the initial send/receive then both cells (the cell on each device) would immediately disappear.
Apr ’21
Reply to NWConnection endPoint info duplicated
Yes, TCP and Websocket, here is the send message: let info = // some String info guard let data = try? NSKeyedArchiver.archivedData(withRootObject: info, requiringSecureCoding: true) else { return } let message = NWProtocolWebSocket.Metadata(opcode: .text) let context = NWConnection.ContentContext(identifier: "send", metadata: [message]) connection.send(content: data, contentContext: context, isComplete: true, completion: .contentProcessed({ (error) in if let error = error { print("\(error.localizedDescription)"); return } print("Success") })) The NWListener, NWBrowser, and NWConnection all are initialized with let tcpOptions = NWProtocolTCP.Options() inside their NWParameters.
Apr ’21
Reply to NWConnection -no Echo from connection.send(content: data, completion : .idempotent)
I was logged in, typed a message with all of my code, described 3 new problems based on your answer, pressed Submit, and the forum message said I was unauthorized. I had to log back in and I lost everything that I just typed This isn't the first time this has happened to me. Apple needs to fix this issue. The same exact thing has happened to me before in AppStoreConnect when responding to the AppReview team in the Resolution Center. I typed an entire message and it said I wasn't logged in even though I was logged in and then I lost everything I typed. Oh man I'm so sick right now. I apologize but I have to send the message again later.
Apr ’21
Reply to NWConnection endPoint info duplicated
I just typed a very descriptive response to the other question that you was helping me out with and I lost it all because it said that I was unauthorized to respond. That is extremely frustrating. I wonder are the 3 new problems that I encountered in my other question based on your last response to that question related to what you said above. From what you are saying my setup is incorrect and that could be the problem right there. Should I start new thread or open a TSI?
Apr ’21
Reply to Disabling Callkit for China Apps
I found this answer - https://stackoverflow.com/a/51319158/4833705 on Stack Overflow. The work around is whatever view controller that is using CallKit you simply make sure that it doesn't get initialized inside that view controller if the country is China. Like this var callObserver: CXCallObserver? override func viewDidLoad() { super.viewDidLoad() if Locale.current.regionCode != "CN" || Locale.current.regionCode != "CHN" { // only init for countries that aren't China callObserver = CXCallObserver()     } }
Apr ’21
Reply to NWConnection -no Echo from connection.send(content: data, completion : .idempotent)
I changed my PeerConnection class to follow the code the way that you did but it's not working correctly. There are 3 issues 1st issue, the echoData is always sent, however inside the PeerConnection class, connection.receive(minimumIncompleteLength.., inside if let data = data, !data.isEmpty { } I call receivedIncoming() again but the returned echoData is nil. 2nd issue, the only way I can get it to keep listening is if I move receivedIncoming() at the very top of the completionHandler like below but the echoData that comes back is is still nil connection.receive(minimumIncompleteLength.. { ... self?.receivedIncoming() if let err = error { ... } if let data = data, !data.isEmpty { // ... } else { print("=-=-=-=-= Receive data is nil -=-=-=-=-=") // returned echoData is always nil } } 3rd issue, inside the same connection.receive(minimumIncompleteLength.., if there are any problems I remove any connections via delegate?.removeIncomingConnection(connection), the ViewController class that conforms to it will remove the connection thus removing the encodedData (a cell shows the data). This is a separate issue relating more so to my other question. But the fact that the returned echoData is nil is causing collateral damage Coded like your example: protocol PeerConnectionDelegate: class {     func sendOutgoing(_ connection: NWConnection)     func removeIncomingConnection(_ connection: NWConnection)     func readDataFromIncomingConnection(_ data: Data, _ connection: NWConnection) } final class PeerConnection: Hashable { // outgoing init is the same // incoming init is the same func startIncomingConnection() { connection.stateUpdateHandler = { [weak self](nwConnectionState) in case .ready: self?.receivedIncoming() } func receivedIncoming() {         guard let connection = connection else { return }         connection.receive(minimumIncompleteLength: 1, maximumLength: 65535) { [weak self](data, context, isComplete, error) in             if let err = error {                 print("received error: (err.localizedDescription)")                 self?.delegate?.removeIncomingConnection(connection)                 return             }             if let data = data, !data.isEmpty {                 let echoString = String(decoding: data, as : UTF8.self)                 if echoString == "12345" {                     print("echo received, stop listening")                     return                 } self?.delegate?.readDataFromIncomingConnection(data, connection) // vc conforms to this                 self?.receivedIncoming()             } else {                 print("=-=-=-=-= Receive data is nil -=-=-=-=-=") // returned echoData gets hit here                 self?.delegate?.removeIncomingConnection(connection)             }         }     } } extension ViewController: PeerConnectionDelegate { // ... other peerConnection Delegate methods func readDataFromIncomingConnection(_ data: Data, _ connection: NWConnection) { guard let decodedData = NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) ... else { return } // display decodedData inside a cell // first make sure connection isn't already in the array, the arrOfConnections is an ivar arrOfConnections.append(connection) let echoData = "12345".data(using: String.Encoding.utf8)         let message = NWProtocolWebSocket.Metadata(opcode: .text) let context = NWConnection.ContentContext(identifier: "send", metadata: [message]) connection.send(content: echoData, contentContext: context, isComplete: true, completion: .contentProcessed({ (error) in           if let error = error { return } print("echoData successfully sent") // this always prints guard let echoData = echoData else { return } let echoString = String(decoding: echoData, as : UTF8.self) if echoString == "12345" {               print("here is the echoData that was sent: \(backToString)") // always prints }     })) }
Apr ’21
Reply to CoreData Crash -objc_release & objc_msgSend
Wow, who would've thought ... The issue was both names began with new as in newBodyText and newHttpsStr. That's not allowed. I found the answer here by @Silfverstrom -https://coderedirect.com/questions/397168/cfstring-release-message-sent-to-deallocated-instance From Apple documentation -https://developer.apple.com/library/ios/releasenotes/objectivec/rn-transitioningtoarc/introduction/introduction.html-: To allow interoperation with manual retain-release code, ARC imposes a constraint on method naming: You cannot give an accessor a name that begins with new. This in turn means that you can’t, for example, declare a property whose name begins with new unless you specify a different getter Once I changed them from newBodyText and newHttpsStr to updatedBodyText and updatedHttpsStr the crash went away.
Dec ’21
Reply to CloudKit -No Containers
If I could delete this I would. It was a weird mistake. On the developer.apple.com sign in page, I signed in with the correct email info but for some reason it says I have 2 developers accounts. One is current (the one from this question) and one is old and no longer active. For some reason I still have access to that old account and that's the account I was using to check my iCloud container. I never realized that old account was still available. Odd mistake considering it's no longer active but I can still access it and it's tied to my current active account.
Jan ’22