Linh Tạ

Quản lý kết nối mạng với swift

Nếu đã từng dùng thư viện bên thứ ba như Reachability hay Alamofire để quản lý kết nối mạng thì kể từ iOS 12 bạn đã có thể làm điều này trực tiếp với Network framework .

NWPathMonitor

NWPathMonitor là class cung cấp khả năng quan sát và xử lý trạng thái khi tình trạng mạng thay đổi. Mỗi khi có connection update, NWPathMonitor sẽ kích hoạt closure pathUpdateHandler với input là NWPath - object chứa các thông tin về connection hiện giờ như status mạng, protocol được support (IPv4, IPv6), connection type (wifi, dữ liệu di động, …). Để bắt đầu quan sát, ta chỉ cần gán pathUpdateHandler và gọi function start(queue:) với queue chạy closure.

Cần lưu ý rằng NWPathMonitor sẽ chạy pathUpdateHandler nếu bất kì thuộc tính nào của connection thay đổi. Tuỳ nghiệp vụ mà bạn có thể quan tâm đến tất cả các thuộc tính hoặc không, tuy nhiên giả sử như chỉ muốn biết về loại kết nối và tình trạng kết nối thì bạn sẽ gặp trường hợp pathUpdateHandler bị gọi nhiều lần khi những thông tin không cần thiết thay đổi.

ConnectionObserver

Để đơn giản hoá việc sử dụng và giới hạn những thông tin quan trọng của connection ta sẽ bọc NWPathMonitor trong class ConnectionObserver.


import Network

protocol ConnectionAttribute: Equatable {
    init(path: NWPath)
}

class ConnectionObserver<T: ConnectionAttribute> {
    var handler: ((T) -> Void)?
    private var monitor: NWPathMonitor

    private(set) var attribute: T {
        didSet {
            guard oldValue != attribute else { return }
            handler?(attribute)
        }
    }

    deinit {
        cancel()
    }

    init(monitor: NWPathMonitor = NWPathMonitor(),
         queue: DispatchQueue = .main,
         handler: ((T) -> Void)? = nil) {
        self.monitor = monitor
        self.attribute = T(path: monitor.currentPath)
        self.handler = handler

        self.monitor.start(queue: queue)
        self.monitor.pathUpdateHandler = { [weak self] path in
            self?.attribute = T(path: path)
        }
    }

    func cancel() {
        monitor.cancel()
    }
}

Protocol ConnectionAttribute đại diện cho những thuộc tính chúng ta quan tâm. Các struct/class conform protocol này sẽ lấy thông tin phù hợp từ NWPath.

Mỗi khi pathUpdateHandler chạy, ConnectionObserver sử dụng NWPath truyền vào để khởi tạo và lưu attribute mới. Bởi ConnectionAttribute tuân thủ Equatable, ta sẽ chỉ chạy closure handler khi attribute mới khác attribute cũ, giúp giải quyết vấn đề nêu ở phần trước.

Việc sử dụng ConnectionObserver rất đơn giản và dễ hiểu


struct BasicConnectionAttribute: Equatable, ConnectionAttribute {
    let isExpensive: Bool
    let hasConnection: Bool

    init(path: NWPath) {
        isExpensive = path.isExpensive
        hasConnection = path.status == .satisfied
    }
}

let observer = ConnectionObserver<BasicConnectionAttribute>() { [weak self] attribute in
    //Logic khi connection thay đổi ...
}


Tổng kết

Với NWPathMonitor chúng ta đã có thể loại bỏ những thư viện bên thứ ba cồng kềnh. Tuy nhiên, mình xin chia buồn tới những bạn vẫn phải support iOS 11 nhé 😢.

Source code: ConnectionObserver