Skip to content

Commit

Permalink
Merge pull request #415 from rebello95/networkmonitor-fix
Browse files Browse the repository at this point in the history
We've started seeing some crashes when using the `CTServiceRadioAccessTechnologyDidChange` notification within `ClientNetworkMonitor ` in production on iOS 12. This is an issue that's been reported in this radar: https://openradar.appspot.com/46873673

To provide a workaround for this problem, I'm adding the option to opt out of the new iOS 12 API and to instead use the stable pre-iOS 12 API.

**I'm planning to release a new version of SwiftGRPC with this fix after it's merged, which is what the second commit of this PR reflects.**
  • Loading branch information
rebello95 authored Mar 28, 2019
2 parents 630dfa5 + f8738a6 commit 7958369
Show file tree
Hide file tree
Showing 4 changed files with 5,327 additions and 5,358 deletions.
20 changes: 13 additions & 7 deletions Sources/SwiftGRPC/Core/ClientNetworkMonitor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import SystemConfiguration
/// Original issue: https://github.com/grpc/grpc-swift/issues/337
open class ClientNetworkMonitor {
private let queue: DispatchQueue
private let useNewCellMonitor: Bool
private let callback: (State) -> Void
private let reachability: SCNetworkReachability

Expand Down Expand Up @@ -61,16 +62,21 @@ open class ClientNetworkMonitor {

/// Designated initializer for the network monitor. Initializer fails if reachability is unavailable.
///
/// - Parameter host: Host to use for monitoring reachability.
/// - Parameter queue: Queue on which to process and update network changes. Will create one if `nil`.
/// Should always be used when accessing properties of this class.
/// - Parameter callback: Closure to call whenever state changes.
public init?(host: String = "google.com", queue: DispatchQueue? = nil, callback: @escaping (State) -> Void) {
/// - Parameter host: Host to use for monitoring reachability.
/// - Parameter queue: Queue on which to process and update network changes. Will create one if `nil`.
/// Should always be used when accessing properties of this class.
/// - Parameter useNewCellMonitor: Whether to use the new cellular monitor introduced in iOS 12.
/// Due to rdar://46873673 this defaults to false to prevent crashes.
/// - Parameter callback: Closure to call whenever state changes.
public init?(host: String = "google.com", queue: DispatchQueue? = nil, useNewCellMonitor: Bool = false,
callback: @escaping (State) -> Void)
{
guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else {
return nil
}

self.queue = queue ?? DispatchQueue(label: "SwiftGRPC.ClientNetworkMonitor.queue")
self.useNewCellMonitor = useNewCellMonitor
self.callback = callback
self.reachability = reachability
self.startMonitoringReachability(reachability)
Expand All @@ -88,7 +94,7 @@ open class ClientNetworkMonitor {

private func startMonitoringCellular() {
let notificationName: Notification.Name
if #available(iOS 12.0, *) {
if #available(iOS 12.0, *), self.useNewCellMonitor {
notificationName = .CTServiceRadioAccessTechnologyDidChange
} else {
notificationName = .CTRadioAccessTechnologyDidChange
Expand All @@ -102,7 +108,7 @@ open class ClientNetworkMonitor {
private func cellularDidChange(_ notification: NSNotification) {
self.queue.async {
let newCellularName: String?
if #available(iOS 12.0, *) {
if #available(iOS 12.0, *), self.useNewCellMonitor {
let cellularKey = notification.object as? String
newCellularName = cellularKey.flatMap { self.cellularInfo.serviceCurrentRadioAccessTechnology?[$0] }
} else {
Expand Down
Loading

0 comments on commit 7958369

Please sign in to comment.