โดย นีโอ อิโกดาโร
บ่อยครั้ง แอปพลิเคชันมือถือจำเป็นต้องมีการเชื่อมต่ออินเทอร์เน็ตที่ใช้งานได้เพื่อให้ทำงานได้อย่างถูกต้อง อย่างไรก็ตาม เป็นเรื่องปกติที่การเชื่อมต่ออินเทอร์เน็ตจะขาดหาย ในกรณีเช่นนี้ ขึ้นอยู่กับนักพัฒนาซอฟต์แวร์ที่จะต้องหาวิธีที่จะทำให้ประสบการณ์นี้น่าจดจำ หรืออย่างน้อยที่สุดก็แจ้งให้ผู้ใช้ทราบ
ในบทความนี้ เราจะมาดูกันว่าเราจะตรวจพบปัญหาการเชื่อมต่ออินเทอร์เน็ตใน Swift ได้อย่างไร และวิธีจัดการกับปัญหาบางอย่าง
นี่คือแอปพลิเคชันตัวอย่างที่เราจะสร้างและวิธีจัดการกับสถานการณ์การเชื่อมต่ออินเทอร์เน็ตที่แตกต่างกัน:

ข้อกำหนด
เพื่อให้คุณสามารถปฏิบัติตามบทความนี้ได้ คุณจะต้องมีข้อกำหนดต่อไปนี้:
- ติดตั้ง Xcode บนเครื่องของคุณแล้ว
- ความรู้เกี่ยวกับภาษาการเขียนโปรแกรม Swift
- Cocoapods ติดตั้งอยู่บนเครื่องของคุณ
เมื่อคุณมีข้อกำหนดข้างต้นแล้ว มาเริ่มกันเลย
การตั้งค่าพื้นที่ทำงานของเรา
ก่อนที่เราจะเริ่ม เราจะสร้างสนามเด็กเล่น ที่นี่เราจะเขียนกรณีการใช้งานทั้งหมดของเราและจัดการกับกรณีเหล่านั้น
Swift มาพร้อมกับการใช้งาน Reachability ของตัวเองเพื่อตรวจจับปัญหาการเชื่อมต่อ แต่เราจะใช้ไลบรารีของบุคคลที่สาม เรากำลังทำเช่นนี้เพราะมันง่ายกว่าและ API แสดงออกได้มากกว่าในตัว
เปิด Xcode และตั้งค่าโปรเจ็กต์ใหม่

โปรเจ็กต์นี้จะเป็นสนามเด็กเล่นง่ายๆ ที่เราสามารถทดลองได้
เพื่อตรวจจับเมื่อการเชื่อมต่อออฟไลน์ เราจะใช้ Reachability.swift ** แพคเกจ มันคือ "การแทนที่ความสามารถในการเข้าถึงของ Apple ที่เขียนใหม่ด้วย Swift พร้อมการปิด"
เปิดเทอร์มินัลของคุณและรันคำสั่งด้านล่าง:
$ pod init
สิ่งนี้จะสร้าง 05 ใหม่ โดยที่เราสามารถประกาศการพึ่งพาของ Cocoapods ได้ เปิด 10 และแทนที่เนื้อหาด้วยโค้ดด้านล่าง:
platform :ios, '9.0'
target 'project_name' do use_frameworks! pod 'ReachabilitySwift' pod 'Alamofire'end
คุณต้องเปลี่ยน
บันทึกไฟล์และรันคำสั่งด้านล่างเพื่อติดตั้ง Pods ให้กับโปรเจ็กต์ของคุณ:
เมื่อการติดตั้งเสร็จสมบูรณ์ ให้เปิด
สร้าง
ในชั้นเรียนข้างต้น เราได้กำหนดฟังก์ชันตัวช่วยสองสามฟังก์ชันที่จะช่วยให้เราเริ่มต้นการตรวจสอบสถานะเครือข่ายได้ เรามี
ใน
เราได้กำหนดฟังก์ชันตัวช่วยอื่นๆ ซึ่งโดยทั่วไปแล้วจะทำให้โค้ดที่รันอยู่นั้นเป็นเรื่องง่าย โดยขึ้นอยู่กับสถานะการเชื่อมต่ออินเทอร์เน็ตของเรา เรามี
โดยทั่วไปการใช้งานตัวช่วยเหล่านี้จะมีลักษณะดังนี้:
นี่ไม่ใช่ Listener กิจกรรมและจะทำงานเพียงครั้งเดียวเท่านั้น หากต้องการใช้ Listener เพื่อรับการเปลี่ยนแปลงเครือข่ายแบบเรียลไทม์ คุณจะต้องใช้
ตอนนี้เรามีคลาสผู้จัดการแล้ว มาดูกันว่าเราจะใช้คลาสนี้ในแอปพลิเคชันได้อย่างไร
บางครั้งแอปพลิเคชันของคุณอาศัยการเชื่อมต่ออินเทอร์เน็ตเป็นอย่างมาก และคุณจำเป็นต้องตรวจสอบสถานะเมื่อเปิดใช้งาน มาดูกันว่าเราจะจัดการเรื่องนี้โดยใช้
สร้างคอนโทรลเลอร์ใหม่ชื่อ
ใน
ในคลาสนี้ เราใช้
เปิด
จากนั้น สร้างตัวควบคุมมุมมองใหม่ในกระดานเรื่องราว ตั้งค่า
ตอนนี้เรามาเรียกใช้แอปพลิเคชันกัน อย่างไรก็ตาม โปรดทราบว่าก่อนที่คุณจะเรียกใช้แอปพลิเคชัน เครื่องพัฒนาของคุณควรออฟไลน์เนื่องจากโปรแกรมจำลอง iOS ใช้การเชื่อมต่ออินเทอร์เน็ตของเครื่อง เมื่อคุณเรียกใช้แอปพลิเคชัน คุณควรได้รับเพจออฟไลน์ที่เราสร้างขึ้น
ตอนนี้ให้เราสร้างตัวควบคุมมุมมองที่จะปรากฏขึ้นเมื่อมีการเชื่อมต่อ
ตอนนี้เราได้สร้างตัวควบคุมมุมมองออฟไลน์และทำงานได้เมื่ออุปกรณ์ออฟไลน์ ให้เราจัดการกับสิ่งที่จะเกิดขึ้นเมื่ออุปกรณ์กลับมาออนไลน์อีกครั้ง
สร้างตัวควบคุมมุมมองการนำทางใหม่บนกระดานเรื่องราวด้านล่างตัวควบคุมมุมมองออฟไลน์ เราจะสร้างตัวควบคุมที่แสดงโพสต์ Reddit ล่าสุด สร้างคลาสตัวควบคุมมุมมองใหม่ที่เรียกว่า
ตอนนี้สร้างการทำต่อแบบแมนนวลชื่อ
ตอนนี้ เปิด
จากนั้นเพิ่มวิธีการด้านล่างลงในคอนโทรลเลอร์:
เพื่อให้แน่ใจว่าเมื่อเปิดแอปขึ้นมา แอปจะตรวจสอบการเชื่อมต่อ จากนั้นหากการเชื่อมต่อพร้อมใช้งาน แอปจะแสดง
เยี่ยมมาก! แต่จะเกิดอะไรขึ้นเมื่อผู้ใช้กด
เปิด
ในตัวควบคุมด้านบน คุณสามารถดูได้ใน
เรายังแทนที่
ตอนนี้ให้เราเพิ่มตรรกะที่จะดึงข้อมูลจาก Reddit และแสดงบน
ใน
ตอนนี้ ให้เราจัดการอีกสถานการณ์หนึ่ง ลองนึกภาพในขณะที่ดูโพสต์ Reddit ล่าสุด คุณจะสูญเสียการเชื่อมต่อ เกิดอะไรขึ้น? มาแสดงหน้าออฟไลน์อีกครั้งเมื่อเกิดเหตุการณ์เช่นนี้
เหมือนที่เคยทำก่อนหน้านี้ ให้สร้างการทำต่อแบบแมนนวลชื่อ
ตอนนี้เพิ่มวิธีการด้านล่างให้กับคอนโทรลเลอร์:
การดำเนินการนี้จะคอยฟังเมื่ออุปกรณ์ออฟไลน์ และหากเกิดเหตุการณ์ดังกล่าว อุปกรณ์จะ
นั่นคือทั้งหมด! เราสามารถจัดการกิจกรรมออฟไลน์และออนไลน์ได้โดยใช้ NetworkManager ใน Swift
ในบทความนี้ เราได้พิจารณาวิธีการตรวจสอบให้แน่ใจว่าแอปพลิเคชันของคุณสามารถจัดการกับกิจกรรมออนไลน์และออฟไลน์ได้เมื่อเกิดขึ้น คุณสามารถใช้สิ่งนี้ได้ทุกเมื่อตามที่คุณต้องการ หากคุณมีคำถามหรือข้อเสนอแนะ โปรดทิ้งไว้ด้านล่างในความคิดเห็น
ซอร์สโค้ดของ Playground นี้มีอยู่ใน GitHub
บทความนี้เผยแพร่ครั้งแรกบน Pusher
เรียนรู้การเขียนโค้ดฟรี หลักสูตรโอเพ่นซอร์สของ freeCodeCamp ช่วยให้ผู้คนมากกว่า 40,000 คนได้งานในตำแหน่งนักพัฒนา เริ่มต้น 23รหัส> พร้อมชื่อโครงการของคุณ ป> $ pod install
33 ไฟล์ในรูทของโปรเจ็กต์ของคุณ นี่จะเป็นการเปิด Xcodeการสร้าง Network Reachability Manager ของเรา
46 ใหม่ ชั้นเรียน คลาสนี้จะจัดเก็บสถานะเครือข่ายและเป็นพร็อกซีอย่างง่ายไปยัง 56 แพคเกจ ในไฟล์ ให้วางโค้ดด้านล่าง: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) } }]
67 นั่นคือซิงเกิลตันและเราสามารถเรียกสิ่งนั้นได้หากเราไม่ต้องการสร้างหลายอินสแตนซ์ของ 75 ชั้นเรียน80 วิธีการเราสร้างอินสแตนซ์ของ 93 จากนั้นเราจะลงทะเบียนการแจ้งเตือนโดยใช้ 102 ชั้นเรียน ตอนนี้ทุกครั้งที่สถานะเครือข่ายเปลี่ยนแปลง การโทรกลับจะระบุด้วย 119 (ซึ่งก็คือ 125 ) จะถูกเรียก เราสามารถใช้สิ่งนี้เพื่อทำบางสิ่งระดับโลกที่จะเปิดใช้งานเมื่อเครือข่ายไม่สามารถเข้าถึงได้136 , 140รหัส> , 155รหัส> และ 166รหัส> .NetworkManager.isReachable { networkManagerInstance in print("Network is available")}
NetworkManager.isUnreachable { networkManagerInstance in print("Network is Unavailable")}
179รหัส> <แข็งแกร่ง> เราจะแสดงตัวอย่างในบทความต่อไป ป> การจัดการความพร้อมใช้งานของเครือข่ายเมื่อเปิดแอปพลิเคชัน
181 ได้อย่างไร ชั้นเรียน195 . เราจะถือว่ามุมมองคอนโทรลเลอร์แรกบนกระดานเรื่องราวเป็นตัวควบคุมการเปิดตัว เราจะพยายามตรวจสอบว่าอุปกรณ์ของผู้ใช้ออนไลน์อยู่หรือไม่ และหากไม่ เราจะสร้างเพจออฟไลน์เพื่อจัดการสิ่งนี้ เพื่อไม่ให้ผู้ใช้เข้าสู่แอปพลิเคชันเลย207 ให้แทนที่เนื้อหาด้วยโค้ดต่อไปนี้: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 ) } }}
215 222 ของ วิธีการยิง 237 วิธีการเมื่อเครือข่ายไม่พร้อมใช้งาน ให้เราสร้างตัวควบคุมมุมมองนั้น สร้างตัวควบคุมมุมมองใหม่ชื่อ 242 .251 ไฟล์และตั้งค่าคลาสที่กำหนดเองของมุมมองแรกเป็น 267 .273 เป็นคลาสที่กำหนดเองสำหรับตัวควบคุมมุมมองใหม่นี้ ตอนนี้สร้างการทำต่อแบบแมนนวลชื่อ 287 ระหว่างตัวควบคุมมุมมองใหม่และ 294 . เมื่อคุณทำเสร็จแล้ว คุณควรจะมีสิ่งที่คล้ายกับสิ่งนี้:
การจัดการเหตุการณ์เมื่ออุปกรณ์ออนไลน์
305 . ตอนนี้ทำให้คลาสนี้เป็นคลาสที่กำหนดเองสำหรับตัวควบคุมมุมมองที่แนบมากับตัวควบคุมมุมมองการนำทาง310 จากตัวควบคุมมุมมองการนำทางไปจนถึงตัวควบคุมมุมมองการเปิดตัวและตัวควบคุมมุมมองออฟไลน์ คุณควรมีสิ่งที่คล้ายกันนี้:
325 คลาสและที่ด้านล่างของ 337 วิธีการเพิ่มดังต่อไปนี้:NetworkManager.isReachable { _ in self.showMainPage()}
private func showMainPage() -> Void { DispatchQueue.main.async { self.performSegue( withIdentifier: "MainController", sender: self ) }}
346 . มิฉะนั้นจะแสดง 359 .369 แล้วเครือข่ายก็กลับมาออนไลน์อีกครั้ง? มาจัดการกับสถานการณ์นั้นกันดีกว่า373 และแทนที่โค้ดด้วยโค้ดด้านล่าง: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) } }}
387 วิธีการที่เราตั้งค่า 392 เสร็จสิ้นเพื่อแสดงตัวควบคุมหลัก ซึ่งหมายความว่าตราบใดที่อุปกรณ์ออฟไลน์ คุณจะคอยดูว่าอุปกรณ์กลับมาออนไลน์อีกครั้งเมื่อใด เมื่อเป็นเช่นนั้น ให้แสดง 400 .410 ด้วย และ 422รหัส> วิธีการเพื่อให้แน่ใจว่าแถบนำทางไม่แสดงบนตัวควบคุมมุมมองออฟไลน์กำลังดึงโพสต์จาก Reddit API ใน Swift
435 ของเรา . เปิดไฟล์และแทนที่เนื้อหาด้วยโค้ดด้านล่าง: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 }}
448 วิธีการเราใช้ 452 เพื่อส่งคำขอ GET ไปยัง Reddit API จากนั้นเราจะแยกวิเคราะห์การตอบสนองและเพิ่มลงใน 460 struct ที่เราสร้างขึ้นที่ด้านบนของไฟล์ ทำให้ข้อมูลที่เรากำลังส่งไปยัง 472 สม่ำเสมอการจัดการเหตุการณ์เมื่ออุปกรณ์ออฟไลน์
486 จาก 495 ไปที่ 501 . ตอนนี้เพิ่มรหัสนี้ที่ด้านล่างของ 511 วิธีการ:network.reachability.whenUnreachable = { reachability in self.showOfflinePage()}
private func showOfflinePage() -> Void { DispatchQueue.main.async { self.performSegue(withIdentifier: "NetworkUnavailable", sender: self) }}
527 .บทสรุป