Skip to content

Instantly share code, notes, and snippets.

@treastrain
Created September 7, 2023 19:00
Show Gist options
  • Save treastrain/f1e018249a678dbf7ec47133205df852 to your computer and use it in GitHub Desktop.
Save treastrain/f1e018249a678dbf7ec47133205df852 to your computer and use it in GitHub Desktop.
`MCBrowserView` for using Multipeer Connectivity `MCBrowserViewController` with SwiftUI (iOS 13.0+, macOS 10.15+, Mac Catalyst 13.1+, tvOS 13.0+, visionOS 1.0+)
//
// MCBrowserView.swift
// You can copy and modify this file and use it with free!
//
// Created by treastrain / Tanaka Ryoga on 2023/09/08.
//
import MultipeerConnectivity
import SwiftUI
@available(iOS 13.0, macOS 10.15, macCatalyst 13.1, tvOS 13.0, visionOS 1.0, *)
@available(watchOS, unavailable)
public struct MCBrowserView {
private enum Parameter {
case serviceType(String)
case browser(MCNearbyServiceBrowser)
}
private let parameter: Parameter
private let session: MCSession
private let minimumNumberOfPeers: Int?
private let maximumNumberOfPeers: Int?
private let shouldPresentNearbyPeer: ((_ peerID: MCPeerID, _ discoveryInfo: [String : String]?) -> Bool)?
private let onFinishHandler: () -> ()
private let onCancelHandler: () -> ()
public init(
serviceType: String,
session: MCSession,
minimumNumberOfPeers: Int? = nil,
maximumNumberOfPeers: Int? = nil,
shouldPresentNearbyPeer: ((_ peerID: MCPeerID, _ discoveryInfo: [String : String]?) -> Bool)? = nil,
onFinish: @escaping () -> (),
onCancel: @escaping () -> ()
) {
self.parameter = .serviceType(serviceType)
self.session = session
self.maximumNumberOfPeers = maximumNumberOfPeers
self.minimumNumberOfPeers = minimumNumberOfPeers
self.shouldPresentNearbyPeer = shouldPresentNearbyPeer
self.onFinishHandler = onFinish
self.onCancelHandler = onCancel
}
public init(
browser: MCNearbyServiceBrowser,
session: MCSession,
minimumNumberOfPeers: Int? = nil,
maximumNumberOfPeers: Int? = nil,
shouldPresentNearbyPeer: ((_ peerID: MCPeerID, _ discoveryInfo: [String : String]?) -> Bool)? = nil,
onFinish: @escaping () -> (),
onCancel: @escaping () -> ()
) {
self.parameter = .browser(browser)
self.session = session
self.minimumNumberOfPeers = minimumNumberOfPeers
self.maximumNumberOfPeers = maximumNumberOfPeers
self.shouldPresentNearbyPeer = shouldPresentNearbyPeer
self.onFinishHandler = onFinish
self.onCancelHandler = onCancel
}
}
#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || os(visionOS)
extension MCBrowserView: UIViewControllerRepresentable {
public func makeUIViewController(context: Context) -> MCBrowserViewController {
let viewController: MCBrowserViewController
switch parameter {
case .serviceType(let serviceType):
viewController = .init(serviceType: serviceType, session: session)
case .browser(let browser):
viewController = .init(browser: browser, session: session)
}
viewController.delegate = context.coordinator
minimumNumberOfPeers.map { viewController.minimumNumberOfPeers = $0 }
maximumNumberOfPeers.map { viewController.maximumNumberOfPeers = $0 }
return viewController
}
public func updateUIViewController(_ uiViewController: MCBrowserViewController, context: Context) {
}
public func makeCoordinator() -> Coordinator {
.init(parent: self)
}
}
#elseif os(macOS)
extension MCBrowserView: NSViewControllerRepresentable {
public func makeNSViewController(context: Context) -> MCBrowserViewController {
let viewController: MCBrowserViewController
switch parameter {
case .serviceType(let serviceType):
viewController = .init(serviceType: serviceType, session: session)
case .browser(let browser):
viewController = .init(browser: browser, session: session)
}
viewController.delegate = context.coordinator
minimumNumberOfPeers.map { viewController.minimumNumberOfPeers = $0 }
maximumNumberOfPeers.map { viewController.maximumNumberOfPeers = $0 }
return viewController
}
public func updateNSViewController(_ nsViewController: MCBrowserViewController, context: Context) {
}
public func makeCoordinator() -> Coordinator {
.init(parent: self)
}
}
#endif
extension MCBrowserView {
public final class Coordinator: NSObject {
private let parent: MCBrowserView
fileprivate init(parent: MCBrowserView) {
self.parent = parent
}
}
}
extension MCBrowserView.Coordinator: MCBrowserViewControllerDelegate {
public func browserViewController(_ browserViewController: MCBrowserViewController, shouldPresentNearbyPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) -> Bool {
parent.shouldPresentNearbyPeer?(peerID, info) ?? true
}
public func browserViewControllerDidFinish(_ browserViewController: MCBrowserViewController) {
parent.onFinishHandler()
}
public func browserViewControllerWasCancelled(_ browserViewController: MCBrowserViewController) {
parent.onCancelHandler()
}
}
@treastrain
Copy link
Author

MCBrowserView for using Multipeer Connectivity MCBrowserViewController with SwiftUI (iOS 13.0+, macOS 10.15+, Mac Catalyst 13.1+, tvOS 13.0+, visionOS 1.0+)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment