From ba3d74a9c54ebed301c995bbfee4a51de5cf7eae Mon Sep 17 00:00:00 2001 From: Nuno Vieira Date: Fri, 8 Dec 2023 18:30:23 +0000 Subject: [PATCH] Make Internet Connection Monitor safer (#2923) * Use serial queue for NWPathMonitor instead of the global queue * Remove Legacy Network Monitor since we now support iOS 12+ only * Update CHANGELOG.md --- CHANGELOG.md | 1 + Package.swift | 2 +- .../StreamChat/ChatClient+Environment.swift | 4 +- .../InternetConnection.swift | 86 +------------------ 4 files changed, 5 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9807bf2424..4bc492fd46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### 🐞 Fixed - Fix `UserInfo.isInvisible` not nullable [#2920](https://github.com/GetStream/stream-chat-swift/pull/2920) - Fix CocoaPods minimum iOS target not in sync with the Xcode project [#2924](https://github.com/GetStream/stream-chat-swift/pull/2924) +- Improve `InternetConnection.Monitor` stability [#2923](https://github.com/GetStream/stream-chat-swift/pull/2923) ### 🔄 Changed - The `UserInfo.isInvisible` is now nullable and `nil` by default [#2920](https://github.com/GetStream/stream-chat-swift/pull/2920) diff --git a/Package.swift b/Package.swift index 892280d6b0..0373d3a204 100644 --- a/Package.swift +++ b/Package.swift @@ -7,7 +7,7 @@ let package = Package( name: "StreamChat", defaultLocalization: "en", platforms: [ - .iOS(.v11), .macOS(.v10_15) + .iOS(.v12), .macOS(.v10_15) ], products: [ .library( diff --git a/Sources/StreamChat/ChatClient+Environment.swift b/Sources/StreamChat/ChatClient+Environment.swift index fd604747a9..4882ba7b7c 100644 --- a/Sources/StreamChat/ChatClient+Environment.swift +++ b/Sources/StreamChat/ChatClient+Environment.swift @@ -69,10 +69,8 @@ extension ChatClient { var internetMonitor: InternetConnectionMonitor { if let monitor = monitor { return monitor - } else if #available(iOS 12, *) { - return InternetConnection.Monitor() } else { - return InternetConnection.LegacyMonitor() + return InternetConnection.Monitor() } } diff --git a/Sources/StreamChat/Utils/InternetConnection/InternetConnection.swift b/Sources/StreamChat/Utils/InternetConnection/InternetConnection.swift index fbbe953db2..e08c386e6a 100644 --- a/Sources/StreamChat/Utils/InternetConnection/InternetConnection.swift +++ b/Sources/StreamChat/Utils/InternetConnection/InternetConnection.swift @@ -149,11 +149,9 @@ extension InternetConnection.Status { // MARK: - Internet Connection Monitor extension InternetConnection { - /// The default Internet connection monitor for iOS 12+. - /// It uses Apple Network API. - @available(iOS 12, *) class Monitor: InternetConnectionMonitor { private var monitor: NWPathMonitor? + private let queue = DispatchQueue(label: "io.getstream.internet-monitor") weak var delegate: InternetConnectionDelegate? @@ -169,7 +167,7 @@ extension InternetConnection { guard monitor == nil else { return } monitor = createMonitor() - monitor?.start(queue: .global()) + monitor?.start(queue: queue) } func stop() { @@ -214,83 +212,3 @@ extension InternetConnection { } } } - -// MARK: Legacy Internet Connection Monitor for iOS 11 only - -extension InternetConnection { - class LegacyMonitor: InternetConnectionMonitor { - /// A Reachability instance for Internet connection monitoring. - private lazy var reachability = createReachability() - - weak var delegate: InternetConnectionDelegate? - - var status: InternetConnection.Status { - if let reachability = reachability { - return status(from: reachability) - } - - return .unknown - } - - func start() { - do { - try reachability?.startNotifier() - } catch { - log.error(error) - } - } - - func stop() { - reachability?.stopNotifier() - } - - private func createReachability() -> Reachability? { - var reachability: Reachability? - - do { - reachability = try Reachability() - reachability?.whenReachable = { [weak self] in self?.updateStatus(with: $0) } - reachability?.whenUnreachable = { [weak self] in self?.updateStatus(with: $0) } - } catch { - log.error(error) - } - - return reachability - } - - private func updateStatus(with reachability: Reachability) { - log.info("Internet Connection info: \(reachability.description)") - - if case .unavailable = reachability.connection { - delegate?.internetConnectionStatusDidChange(status: .unavailable) - return - } - - let quality: InternetConnection.Quality - - if case .cellular = reachability.connection { - quality = .expensive - } else { - quality = .great - } - - delegate?.internetConnectionStatusDidChange(status: .available(quality)) - } - - private func status(from reachability: Reachability) -> InternetConnection.Status { - if case .unavailable = reachability.connection { - return .unavailable - } - - let quality: InternetConnection.Quality - - if case .cellular = reachability.connection { - quality = .expensive - } else { - quality = .great - } - - return .available(quality) - } - } -}