Computer >> Hướng Dẫn Máy Tính >  >> Kết Nối Mạng >> Internet

Phát hiện và quản lý kết nối Internet trong Swift:Hướng dẫn thực hành

Bởi Neo Ighodaro

Thông thường, các ứng dụng di động cần có kết nối Internet đang hoạt động để hoạt động bình thường. Tuy nhiên, việc mất kết nối internet là điều bình thường. Trong những trường hợp như thế này, nhà phát triển có trách nhiệm tìm ra cách để mang lại trải nghiệm dễ chịu hơn hoặc ít nhất là thông báo cho người dùng.

Trong bài viết này, chúng ta sẽ xem cách có thể phát hiện các sự cố kết nối internet trong Swift và một số cách có thể xử lý nó.

Đây là ứng dụng mẫu mà chúng tôi sẽ xây dựng và cách ứng dụng này xử lý các tình huống kết nối Internet khác nhau:

Phát hiện và quản lý kết nối Internet trong Swift:Hướng dẫn thực hành

Yêu cầu

Để có thể theo dõi bài viết này, bạn cần đáp ứng các yêu cầu sau:

  • Xcode được cài đặt trên máy của bạn.
  • Kiến thức về ngôn ngữ lập trình Swift.
  • Cocoapod được cài đặt trên máy của bạn.

Khi bạn đã có những yêu cầu trên, hãy bắt tay vào thực hiện.

Thiết lập không gian làm việc của chúng tôi

Trước khi bắt đầu, chúng ta sẽ tạo một sân chơi. Đây là nơi chúng ta sẽ viết tất cả các trường hợp sử dụng và xử lý chúng.

Swift đi kèm với triển khai Khả năng hiển thị riêng để phát hiện các sự cố kết nối, nhưng chúng tôi sẽ sử dụng thư viện của bên thứ ba. Chúng tôi làm điều này vì nó dễ dàng hơn và API có tính biểu cảm cao hơn API được tích hợp sẵn.

Mở Xcode và thiết lập một dự án mới.

Phát hiện và quản lý kết nối Internet trong Swift:Hướng dẫn thực hành

Dự án này sẽ là một sân chơi đơn giản mà chúng ta có thể thử nghiệm.

Để phát hiện khi kết nối ngoại tuyến, chúng tôi sẽ sử dụng Reachability.swift ** gói. Nó là “sự thay thế cho Khả năng tiếp cận của Apple được viết lại bằng Swift với các phần đóng”.

Mở terminal của bạn và chạy lệnh bên dưới:

$ pod init

Điều này sẽ tạo một Podfile mới nơi chúng ta có thể khai báo các phần phụ thuộc của Cocoapod. Mở Podfile và thay thế nội dung bằng mã bên dưới:

platform :ios, '9.0'
target 'project_name' do use_frameworks! pod 'ReachabilitySwift' pod 'Alamofire'end

Bạn cần thay thế **project_name** với tên dự án của bạn.

Lưu tệp và chạy lệnh bên dưới để cài đặt Pod vào dự án của bạn:

$ pod install

Khi quá trình cài đặt hoàn tất, hãy mở *.xcworkspace tập tin trong thư mục gốc của dự án của bạn. Thao tác này sẽ khởi chạy Xcode.

Tạo Trình quản lý khả năng tiếp cận mạng của chúng tôi

Tạo một NetworkManager mới lớp học. Lớp này sẽ lưu trữ trạng thái mạng và là proxy đơn giản cho Reachability gói. Trong tệp, dán mã bên dưới:

import Foundationimport Reachability
class NetworkManager: NSObject {
 var reachability: Reachability!
 static let sharedInstance: NetworkManager = { return NetworkManager() }()
 override init() { super.init()
 // Initialise reachability reachability = Reachability()!
 // Register an observer for the network status NotificationCenter.default.addObserver( self, selector: #selector(networkStatusChanged(_:)), name: .reachabilityChanged, object: reachability )
 do { // Start the network status notifier try reachability.startNotifier() } catch { print("Unable to start notifier") } }
 @objc func networkStatusChanged(_ notification: Notification) { // Do something globally here! }
 static func stopNotifier() -> Void { do { // Stop the network status notifier try (NetworkManager.sharedInstance.reachability).startNotifier() } catch { print("Error stopping notifier") } }
 // Network is reachable static func isReachable(completed: @escaping (NetworkManager) -> Void) { if (NetworkManager.sharedInstance.reachability).connection != .none { completed(NetworkManager.sharedInstance) } }
 // Network is unreachable static func isUnreachable(completed: @escaping (NetworkManager) -> Void) { if (NetworkManager.sharedInstance.reachability).connection == .none { completed(NetworkManager.sharedInstance) } }
 // Network is reachable via WWAN/Cellular static func isReachableViaWWAN(completed: @escaping (NetworkManager) -> Void) { if (NetworkManager.sharedInstance.reachability).connection == .cellular { completed(NetworkManager.sharedInstance) } }
 // Network is reachable via WiFi static func isReachableViaWiFi(completed: @escaping (NetworkManager) -> Void) { if (NetworkManager.sharedInstance.reachability).connection == .wifi { completed(NetworkManager.sharedInstance) } }]

Trong lớp trên, chúng ta đã xác định một số hàm trợ giúp sẽ giúp chúng ta bắt đầu theo dõi trạng thái mạng. Chúng tôi có sharedInstance đó là một singleton và chúng ta có thể gọi nó nếu không muốn tạo nhiều phiên bản của NetworkManager lớp học.

Trong init phương thức này, chúng tôi tạo một phiên bản của Reachability và sau đó chúng tôi đăng ký thông báo bằng NotificationCenter lớp học. Bây giờ, mỗi khi trạng thái mạng thay đổi, lệnh gọi lại được chỉ định bởi NotificationCenter (tức là networkStatusChanged ) sẽ được gọi. Chúng tôi có thể sử dụng điều này để thực hiện điều gì đó mang tính toàn cầu được kích hoạt khi mạng không thể truy cập được.

Chúng tôi đã xác định các hàm trợ giúp khác thường giúp việc chạy mã, tùy thuộc vào trạng thái kết nối internet của chúng tôi, trở nên dễ dàng. Chúng tôi có *isReachable* , *isUnreachable* , *isReachableViaWWAN**isReachableViaWiFi* .

Cách sử dụng một trong những trợ giúp này nhìn chung sẽ như sau:

NetworkManager.isReachable { networkManagerInstance in print("Network is available")}
NetworkManager.isUnreachable { networkManagerInstance in print("Network is Unavailable")}

Đây không phải là trình xử lý sự kiện và sẽ chỉ chạy một lần. Để sử dụng trình nghe nhằm nhận biết các thay đổi của mạng trong thời gian thực, bạn cần sử dụng NetworkManager.sharedInstance.reachability.whenReachable . Chúng tôi sẽ đưa ra một ví dụ ở phần sau của bài viết.

Bây giờ chúng ta đã có lớp người quản lý, hãy xem cách chúng ta có thể sử dụng lớp này trong một ứng dụng.

Xử lý tính khả dụng của mạng khi khởi chạy ứng dụng

Đôi khi, ứng dụng của bạn phụ thuộc rất nhiều vào kết nối internet và bạn cần phát hiện trạng thái khi khởi chạy. Hãy xem cách chúng ta có thể xử lý việc này bằng cách sử dụng NetworkManager lớp học.

Tạo bộ điều khiển mới có tên LaunchViewController . Chúng tôi sẽ coi chế độ xem bộ điều khiển đầu tiên trên bảng phân cảnh là bộ điều khiển khởi chạy. Chúng tôi sẽ cố gắng phát hiện xem thiết bị của người dùng có trực tuyến hay không và nếu không, chúng tôi sẽ tạo một trang ngoại tuyến để xử lý việc này để người dùng hoàn toàn không truy cập vào ứng dụng.

Trong LaunchController , thay thế nội dung bằng đoạn mã sau:

import UIKit
class LaunchViewController: UIViewController { let network: NetworkManager = NetworkManager.sharedInstance
 override func viewDidLoad() { super.viewDidLoad()
 NetworkManager.isUnreachable { _ in self.showOfflinePage() } }
 private func showOfflinePage() -> Void { DispatchQueue.main.async { self.performSegue( withIdentifier: "NetworkUnavailable", sender: self ) } }}

Trong lớp này, chúng tôi sử dụng NetworkManager của *isUnreachable* phương pháp kích hoạt showOffline phương pháp khi mạng không khả dụng. Hãy để chúng tôi tạo bộ điều khiển xem đó. Tạo bộ điều khiển chế độ xem mới có tên OfflineViewController .

Mở Main.storyboard tệp và đặt lớp tùy chỉnh của chế độ xem đầu tiên thành LaunchViewController .

Tiếp theo, tạo bộ điều khiển chế độ xem mới trong bảng phân cảnh. Đặt OfflineViewController làm lớp tùy chỉnh cho bộ điều khiển chế độ xem mới này. Bây giờ hãy tạo một segue thủ công có tên NetworkUnavailable giữa bộ điều khiển chế độ xem mới và LaunchViewController . Khi hoàn tất, bạn sẽ có một cái gì đó tương tự như thế này:

Phát hiện và quản lý kết nối Internet trong Swift:Hướng dẫn thực hành

Bây giờ hãy chạy ứng dụng. Tuy nhiên, xin lưu ý rằng trước khi bạn chạy ứng dụng, máy phát triển của bạn phải ngoại tuyến vì trình mô phỏng iOS sử dụng kết nối internet của máy. Khi chạy ứng dụng, bạn sẽ nhận được trang ngoại tuyến mà chúng tôi đã tạo.

Bây giờ chúng ta hãy tạo một bộ điều khiển xem hiển thị khi có kết nối.

Xử lý sự kiện khi thiết bị trực tuyến

Bây giờ chúng ta đã tạo Bộ điều khiển chế độ xem ngoại tuyến và nó hoạt động khi thiết bị ngoại tuyến, hãy cùng chúng tôi xử lý những gì xảy ra khi thiết bị trực tuyến trở lại.

Tạo bộ điều khiển chế độ xem điều hướng mới trên bảng phân cảnh bên dưới Bộ điều khiển chế độ xem ngoại tuyến. Chúng tôi sẽ tạo bộ điều khiển hiển thị các bài đăng Reddit mới nhất. Tạo một lớp trình điều khiển chế độ xem mới có tên PostsTableViewController . Bây giờ, hãy đặt lớp này làm lớp tùy chỉnh cho bộ điều khiển chế độ xem được gắn vào Bộ điều khiển chế độ xem điều hướng.

Bây giờ hãy tạo một segue thủ công có tên MainController từ Bộ điều khiển Chế độ xem Điều hướng đến Bộ điều khiển Chế độ xem Khởi chạy và Bộ điều khiển Chế độ xem Ngoại tuyến. Bạn nên có một cái gì đó tương tự như thế này:

Phát hiện và quản lý kết nối Internet trong Swift:Hướng dẫn thực hành

Bây giờ, hãy mở LaunchViewController lớp và ở cuối viewDidLoad phương pháp thêm vào như sau:

NetworkManager.isReachable { _ in self.showMainPage()}

Sau đó thêm phương thức bên dưới vào bộ điều khiển:

private func showMainPage() -> Void { DispatchQueue.main.async { self.performSegue( withIdentifier: "MainController", sender: self ) }}

Điều này sẽ đảm bảo rằng khi ứng dụng được khởi chạy, nó sẽ kiểm tra khả năng kết nối và sau đó, nếu có kết nối, nó sẽ hiển thị PostsTableViewController . Nếu không nó sẽ hiển thị OfflineViewController .

Tuyệt vời! Nhưng điều gì xảy ra khi người dùng nhấn OfflineViewController và sau đó mạng trở lại trực tuyến? Hãy xử lý tình huống đó.

Mở OfflineViewController và thay thế mã bằng mã bên dưới:

import UIKit
class OfflineViewController: UIViewController { let network = NetworkManager.sharedInstance
 override func viewDidLoad() { super.viewDidLoad()
 // If the network is reachable show the main controller network.reachability.whenReachable = { _ in self.showMainController() } }
 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated)
 navigationController?.setNavigationBarHidden(true, animated: animated) }
 override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated)
 navigationController?.setNavigationBarHidden(false, animated: animated) }
 private func showMainController() -> Void { DispatchQueue.main.async { self.performSegue(withIdentifier: "MainController", sender: self) } }}

Trong bộ điều khiển ở trên, bạn có thể thấy, trong viewDidLoad phương thức mà chúng tôi đặt whenReachable hoàn thành để hiển thị bộ điều khiển chính. Điều này có nghĩa là, miễn là thiết bị ngoại tuyến, bạn sẽ theo dõi thời điểm thiết bị trực tuyến trở lại. Khi đó, hãy trình bày PostsTableViewController .

Chúng tôi cũng ghi đè viewWillAppearviewWillDisappear các phương pháp để đảm bảo thanh điều hướng không hiển thị trên Bộ điều khiển Chế độ xem Ngoại tuyến.

Tìm nạp bài đăng từ API Reddit trong Swift

Bây giờ, hãy thêm logic sẽ tìm nạp dữ liệu từ Reddit và hiển thị trên PostsTableViewController của chúng tôi . Mở tệp và thay thế nội dung bằng mã bên dưới:

import UIKitimport Alamofire
struct RedditPost { let title: String! let subreddit: String!}
class PostsTableViewController: UITableViewController { var posts = [RedditPost]()
 let network = NetworkManager.sharedInstance
 override func viewDidLoad() { super.viewDidLoad() navigationItem.title = "Latest Posts"
 // Fetch the posts and then reload the table fetchPosts { posts in self.posts = posts self.tableView.reloadData() } }
 private func fetchPosts(completion: @escaping (_ posts: [RedditPost]) -> Void) -> Void { // Send a request to the Reddit API Alamofire.request("https://api.reddit.com").validate().responseJSON { response in switch response.result { case .success(let JSON): let data = JSON as! [String:AnyObject] guard let children = data["data"]!["children"] as? [AnyObject] else { return } var posts = [RedditPost]()
 // Loop through the Reddit posts and then assign a post to the posts array for child in 0...children.count-1 { let post = children[child]["data"] as! [String: AnyObject]
 posts.append(RedditPost( title: post["title"] as! String, subreddit: "/r/" + (post["subreddit"] as! String) )) }
 DispatchQueue.main.async { completion(posts) } case .failure(let error): print(error) } } }
 override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }
 // MARK: - Table view data source override func numberOfSections(in tableView: UITableView) -> Int { return 1 }
 // Return the number of posts available override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.posts.count }
 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) let post = posts[indexPath.row] as RedditPost cell.textLabel?.text = post.title cell.detailTextLabel?.text = post.subreddit return cell }}

Trong fetchPosts phương pháp này, chúng tôi sử dụng Alamofire để gửi yêu cầu GET tới API Reddit. Sau đó, chúng tôi phân tích phản hồi và thêm nó vào RedditPost struct chúng tôi đã tạo ở đầu tệp. Điều này làm cho dữ liệu chúng ta chuyển tới tableView nhất quán.

Xử lý sự kiện khi thiết bị ngoại tuyến

Bây giờ, chúng ta hãy xử lý một kịch bản nữa. Hãy tưởng tượng khi xem các bài đăng mới nhất của Reddit, bạn bị mất kết nối. Điều gì xảy ra? Hãy hiển thị lại trang ngoại tuyến khi điều đó xảy ra.

Như đã thực hiện trước đó, hãy tạo một segue thủ công có tên NetworkUnavailable từ PostsTableViewController tới OfflineViewController . Bây giờ hãy thêm mã này vào cuối viewDidLoad phương pháp:

network.reachability.whenUnreachable = { reachability in self.showOfflinePage()}

Bây giờ thêm phương thức bên dưới vào bộ điều khiển:

private func showOfflinePage() -> Void { DispatchQueue.main.async { self.performSegue(withIdentifier: "NetworkUnavailable", sender: self) }}

Điều này sẽ lắng nghe khi thiết bị ngoại tuyến và nếu điều đó xảy ra, nó sẽ showOfflinePage .

Thế thôi! Chúng tôi đã có thể xử lý các sự kiện ngoại tuyến và trực tuyến bằng Trình quản lý mạng trong Swift.

Kết luận

Trong bài viết này, chúng tôi đã xem xét cách đảm bảo ứng dụng của bạn có thể xử lý các sự kiện trực tuyến và ngoại tuyến khi chúng xảy ra. Bạn luôn có thể thực hiện điều này theo bất kỳ cách nào bạn muốn. Nếu bạn có bất kỳ câu hỏi hoặc phản hồi nào, hãy để lại chúng ở phần bình luận bên dưới.

Mã nguồn của sân chơi này có sẵn trên GitHub.

Bài viết này được xuất bản lần đầu trên Pusher.

Học cách viết mã miễn phí. Chương trình giảng dạy mã nguồn mở của freeCodeCamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu