Last active
March 9, 2022 19:43
-
-
Save ralfebert/2ee9df7a88fb817047e59bcb8138b19d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import MultipeerConnectivity | |
import os | |
import SwiftUI | |
class ColorModel: NSObject, ObservableObject { | |
private let serviceType = "example-color" | |
private let session: MCSession | |
private let myPeerId = MCPeerID(displayName: UIDevice.current.name) | |
private let serviceAdvertiser: MCNearbyServiceAdvertiser | |
private let serviceBrowser: MCNearbyServiceBrowser | |
private let log = Logger() | |
@Published var currentColor: Color? = nil { | |
didSet { | |
if oldValue != currentColor, let currentColor = currentColor { | |
self.send(color: currentColor) | |
} | |
} | |
} | |
let colors = [Color.red, .green, .blue, .yellow, .brown] | |
override init() { | |
precondition(Thread.isMainThread) | |
self.session = MCSession(peer: myPeerId) | |
self.serviceAdvertiser = MCNearbyServiceAdvertiser(peer: myPeerId, discoveryInfo: nil, serviceType: serviceType) | |
self.serviceBrowser = MCNearbyServiceBrowser(peer: myPeerId, serviceType: serviceType) | |
super.init() | |
session.delegate = self | |
serviceAdvertiser.delegate = self | |
serviceBrowser.delegate = self | |
serviceAdvertiser.startAdvertisingPeer() | |
serviceBrowser.startBrowsingForPeers() | |
} | |
deinit { | |
self.serviceAdvertiser.stopAdvertisingPeer() | |
self.serviceBrowser.stopBrowsingForPeers() | |
} | |
private func send(color: Color) { | |
precondition(Thread.isMainThread) | |
do { | |
var r: CGFloat = 0 | |
var g: CGFloat = 0 | |
var b: CGFloat = 0 | |
var o: CGFloat = 0 | |
UIColor(color).getRed(&r, green: &g, blue: &b, alpha: &o) | |
let components = [r, g, b] | |
if !self.session.connectedPeers.isEmpty { | |
try session.send(JSONEncoder().encode(components), toPeers: session.connectedPeers, with: .reliable) | |
} | |
log.info("sendColor: \(components) to \(self.session.connectedPeers.count) peers") | |
} catch { | |
log.error("Error for sending: \(String(describing: error))") | |
} | |
} | |
} | |
extension ColorModel: MCNearbyServiceAdvertiserDelegate { | |
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didNotStartAdvertisingPeer error: Error) { | |
precondition(Thread.isMainThread) | |
log.error("ServiceAdvertiser didNotStartAdvertisingPeer: \(String(describing: error))") | |
} | |
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) { | |
precondition(Thread.isMainThread) | |
log.info("didReceiveInvitationFromPeer \(peerID)") | |
invitationHandler(true, session) | |
} | |
} | |
extension ColorModel: MCNearbyServiceBrowserDelegate { | |
func browser(_ browser: MCNearbyServiceBrowser, didNotStartBrowsingForPeers error: Error) { | |
log.error("ServiceBrowser didNotStartBrowsingForPeers: \(String(describing: error))") | |
} | |
func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String: String]?) { | |
log.info("ServiceBrowser found peer: \(peerID)") | |
browser.invitePeer(peerID, to: session, withContext: nil, timeout: 10) | |
} | |
func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) { | |
log.info("ServiceBrowser lost peer: \(peerID)") | |
} | |
} | |
extension ColorModel: MCSessionDelegate { | |
func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) { | |
log.info("peer \(peerID) didChangeState: \(state.debugDescription)") | |
} | |
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) { | |
if let color = try? JSONDecoder().decode([Double].self, from: data) { | |
log.info("didReceive color \(color)") | |
DispatchQueue.main.async { | |
self.currentColor = Color(red: color[0], green: color[1], blue: color[2]) | |
} | |
} else { | |
log.info("didReceive invalid value \(data.count) bytes") | |
} | |
} | |
public func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) { | |
log.error("Receiving streams is not supported") | |
} | |
public func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) { | |
log.error("Receiving resources is not supported") | |
} | |
public func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) { | |
log.error("Receiving resources is not supported") | |
} | |
} | |
extension MCSessionState: CustomDebugStringConvertible { | |
public var debugDescription: String { | |
switch self { | |
case .notConnected: | |
return "notConnected" | |
case .connecting: | |
return "connecting" | |
case .connected: | |
return "connected" | |
@unknown default: | |
return "\(rawValue)" | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment