Проверка наличия интернет-соединения в Swift — простое и надёжное решение
Использование NWPathMonitor для проверки интернет-соединения
Начиная с iOS 12, Apple рекомендует использовать NWPathMonitor из фреймворка Network для мониторинга сетевого соединения. Это современная и простая в использовании замена устаревшей Reachability. Вот пошаговое решение.
1. Создаём менеджер сетевого мониторинга
Лучше вынести логику в отдельный класс, чтобы переиспользовать её во всём приложении:
import Foundation
import Network
final class NetworkMonitor {
static let shared = NetworkMonitor()
private let monitor = NWPathMonitor()
private let queue = DispatchQueue.global(qos: .background)
private(set) var isConnected: Bool = false
private(set) var connectionType: ConnectionType = .unknown
enum ConnectionType {
case wifi
case cellular
case ethernet
case unknown
}
private init() {
startMonitoring()
}
func startMonitoring() {
monitor.pathUpdateHandler = { [weak self] path in
self?.isConnected = path.status == .satisfied
self?.getConnectionType(path)
}
monitor.start(queue: queue)
}
func stopMonitoring() {
monitor.cancel()
}
private func getConnectionType(_ path: NWPath) {
if path.usesInterfaceType(.wifi) {
connectionType = .wifi
} else if path.usesInterfaceType(.cellular) {
connectionType = .cellular
} else if path.usesInterfaceType(.wiredEthernet) {
connectionType = .ethernet
} else {
connectionType = .unknown
}
}
}
2. Используем в ViewController
Теперь можно проверять соединение перед запросом:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Начинаем мониторинг (обычно в AppDelegate или SceneDelegate)
// Но можно и здесь, если нужно только для этого экрана
}
@IBAction func fetchDataTapped() {
guard NetworkMonitor.shared.isConnected else {
showNoInternetAlert()
return
}
fetchData()
}
func fetchData() {
let url = URL(string: "https://api.example.com/data")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
DispatchQueue.main.async {
if let data = data {
print("Data received: \(data)")
} else if let error = error {
print("Error: \(error.localizedDescription)")
}
}
}
task.resume()
}
private func showNoInternetAlert() {
let alert = UIAlertController(
title: "Нет интернета",
message: "Пожалуйста, проверьте подключение к сети и попробуйте снова.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .default))
present(alert, animated: true)
}
}
3. Настройка при запуске приложения
Лучше всего запускать мониторинг один раз при старте приложения, например, в AppDelegate:
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Активируем мониторинг сети
_ = NetworkMonitor.shared
return true
}
}
4. Дополнительные возможности
- Реагирование на изменения: Подпишитесь на уведомления через
NotificationCenterили используйте Combine для обновления UI в реальном времени. - Проверка типа соединения: Вы можете адаптировать поведение приложения (например, отключить загрузку больших файлов на сотовой сети).
- Производительность:
NWPathMonitorработает в фоновом потоке и не блокирует главный поток.
Это решение полностью нативное, не требует сторонних библиотек и работает на iOS 12+. Если вам нужно поддерживать более старые версии, придётся использовать устаревшую Reachability, но для современных проектов NWPathMonitor — лучший выбор.
Альтернативный подход: простая проверка перед каждым запросом
Если вам не нужен постоянный мониторинг сети, а только проверка перед конкретным запросом, можно использовать простую функцию с NWPathMonitor в синхронном режиме. Однако помните, что это может заблокировать поток на короткое время.
import Foundation
import Network
func isInternetAvailable() -> Bool {
let monitor = NWPathMonitor()
let queue = DispatchQueue(label: "NetworkMonitor")
var available = false
let semaphore = DispatchSemaphore(value: 0)
monitor.pathUpdateHandler = { path in
available = path.status == .satisfied
semaphore.signal()
}
monitor.start(queue: queue)
semaphore.wait()
monitor.cancel()
return available
}
// Использование
if isInternetAvailable() {
print("Интернет есть")
} else {
print("Нет интернета")
}
Этот подход проще, но имеет недостатки:
- Блокирует текущий поток (используйте только в фоновых потоках).
- Не подходит для асинхронных операций.
- Создаёт новый монитор при каждом вызове, что менее эффективно.
Рекомендую использовать первый вариант с синглтоном для production-кода, а этот — только для быстрых прототипов или тестирования.
Ответов пока нет.
Войдите чтобы оставить ответ