Skip to content

Instantly share code, notes, and snippets.

@doozMen
Created February 25, 2022 15:44
Show Gist options
  • Save doozMen/0b5fc54c765bccb7c13792caa4eaa51c to your computer and use it in GitHub Desktop.
Save doozMen/0b5fc54c765bccb7c13792caa4eaa51c to your computer and use it in GitHub Desktop.
Uses bonjour networking to relialby check if user has granted local network access with async await as of iOS14
import Foundation
import Network
/// Uses bonjour networking to relialby check if user has granted local network access
/// How to use:
/// Add LocalNetworkAuthorization class to your project
/// Open .plist file and add "_bonjour._tcp", "_lnp._tcp.", as a values under "Bonjour services"
/// Call requestAuthorization() to trigger the prompt or get the authorization status if it already been approved/denied
/// about the author: https://stackoverflow.com/a/67758105/705761
public class LocalNetworkAuthorization: NSObject {
private var browser: NWBrowser?
private var netService: NetService?
private var completion: ((Bool) -> Void)?
public func requestAuthorization() async -> Bool {
return await withCheckedContinuation { continuation in
requestAuthorization() { result in
continuation.resume(returning: result)
}
}
}
private func requestAuthorization(completion: @escaping (Bool) -> Void) {
self.completion = completion
// Create parameters, and allow browsing over peer-to-peer link.
let parameters = NWParameters()
parameters.includePeerToPeer = true
// Browse for a custom service type.
let browser = NWBrowser(for: .bonjour(type: "_bonjour._tcp", domain: nil), using: parameters)
self.browser = browser
browser.stateUpdateHandler = { newState in
switch newState {
case .failed(let error):
print(error.localizedDescription)
case .ready, .cancelled:
break
case let .waiting(error):
print("Local network permission has been denied: \(error)")
self.reset()
self.completion?(false)
default:
break
}
}
self.netService = NetService(domain: "local.", type:"_lnp._tcp.", name: "LocalNetworkPrivacy", port: 1100)
self.netService?.delegate = self
self.browser?.start(queue: .main)
self.netService?.publish()
}
private func reset() {
self.browser?.cancel()
self.browser = nil
self.netService?.stop()
self.netService = nil
}
}
extension LocalNetworkAuthorization : NetServiceDelegate {
public func netServiceDidPublish(_ sender: NetService) {
self.reset()
print("Local network permission has been granted")
completion?(true)
}
}
@Rytiggy
Copy link

Rytiggy commented Nov 2, 2022

netServiceDidPublish never gets called, could you help me understand why?

@theoks
Copy link

theoks commented Nov 6, 2022

@Rytiggy you need to schedule the netService on a run loop (I did it on the main runloop)

netService?.schedule(in: .main, forMode: .common)

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