1. 程式人生 > >[Xcode10 實際操作]八、網路與多執行緒-(8)使用同步Get方式查詢某地天氣

[Xcode10 實際操作]八、網路與多執行緒-(8)使用同步Get方式查詢某地天氣

本文將演示如果通過Get的方式,請求某地天氣資訊,同步獲取網路資料,

一旦傳送同步請求,程式將停止使用者互動,直至伺服器返回資料。

為了增強資料訪問的安全性,從9.0版本開始,Xcode預設會把所有的網路請求,修改為https安全請求。

也可以修改配置檔案,以支援普通的網路請求。

點選開啟【Info.plist】屬性列表檔案。

在配置檔案編輯區的空白處,點選滑鼠右鍵,彈出功能選單。

->【Add Row】

->【Information Property List】在鍵列表中選擇需要設定的鍵【App Transport Security Settings】

->點選鍵左側的右向箭頭,顯示所屬的選項。

->點選鍵右側的【+】新增一個子屬性。

->在鍵名輸入框內選擇【Allow Arbitrary Loads】選擇允許載入非安全請求的屬性名稱。

->點選子屬性的值,更改布林值為真Yes。

在專案導航區,開啟檢視控制器的程式碼檔案【ViewController.swift】

 1 import UIKit
 2 
 3 class ViewController: UIViewController {
 4     
 5     //給當前檢視控制器類,新增一個標籤屬性。
 6     //該標籤物件,將用來顯示遠端伺服器返回的資訊
 7     var label = UILabel()
8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 // Do any additional setup after loading the view, typically from a nib. 12 13 //設定標籤物件的位置在(20,40),尺寸為(280,500) 14 label.frame = CGRect(x: 20, y: 40, width: 280, height: 500) 15 //設定標籤物件的文字內容
16 label.text = "Loading..." 17 //設定標籤物件的字型和大小 18 label.font = UIFont(name: "Arial", size: 12) 19 //設定標籤物件的背景顏色為淺灰色 20 label.backgroundColor = UIColor.lightGray 21 //設定標籤物件的行數屬性值為0,表示不限制標籤物件的行數。 22 label.numberOfLines = 0 23 //遠端伺服器有可能返回較多的文字內容, 24 //在此設定標籤物件在進行換行時,保留所有的字元 25 label.lineBreakMode = NSLineBreakMode.byWordWrapping 26 //將設定好的標籤物件,新增到當前檢視控制器的根檢視 27 self.view.addSubview(label) 28 29 //建立一個網址物件,指定請求網路資料的網址。 30 //網址最後面的一串數字,表示某地區的編號,此處代表北京地區 31 let url = URL(string: "http://www.weather.com.cn/data/sk/101010100.html") 32 33 //建立一個網路請求物件,引數說明: 34 //1.代表請求訪問的路徑 35 //2.代表網路請求的快取協議 36 //3.代表網路請求的超時時間 37 let request = URLRequest.init(url:url!, //1.代表請求訪問的路徑 38 cachePolicy: NSURLRequest.CachePolicy.useProtocolCachePolicy, //2.代表網路請求的快取協議 39 timeoutInterval: 30)//3.代表網路請求的超時時間 40 41 //初始化一個訊號量,它是一種用來控制併發訪問資源的機制, 42 //常用於多執行緒中,可以控制併發執行緒的數量。 43 //這裡設定訊號量為0,使執行緒一直等待,從而產生同步請求的效果。 44 let semaphore = DispatchSemaphore(value: 0) 45 46 //網址會話URLSession在2013年釋出,蘋果對它的定位是作為舊的網路請求介面的替代者。 47 //這裡獲得網址會話的單例物件 48 let session = URLSession.shared 49 //所有網路請求工作,都是通過網址會話任務物件來完成的。 50 //可以使用閉包、代理或者兩者混合的方式,來建立網路請求任務。 51 let task = session.dataTask(with: request, completionHandler: {(data, response, error) -> Void in 52 //如果出現網路請求錯誤, 53 if error != nil{ 54 //則在控制檯列印輸出錯誤程式碼和錯誤資訊 55 print(error.debugDescription) 56 }else{ 57 //將網路返回的資料物件,根據指定的編碼方式,轉換為字串 58 let result = String(data: data!, encoding: String.Encoding.utf8) 59 //然後返回主執行緒, 60 DispatchQueue.main.async(execute: { () -> Void in 61 //更新標籤物件的文字內容 62 //介面元素的重新整理,需要在主執行緒進行 63 self.label.text = result! as String 64 }) 65 } 66 67 //將訊號量進行傳送,使訊號量加1, 68 //此時其他等待中的執行緒就會被喚醒, 69 //從而完成同步網路請求的操作 70 semaphore.signal() 71 }) 72 73 //任務建立後,呼叫resume方法開始工作。 74 task.resume() 75 76 //等待訊號量,timeout引數可以控制等待的最長時間,distantFuture表示永久等待 77 _ = semaphore.wait(timeout: DispatchTime.distantFuture) 78 //在網路的同步請求結束之後,在控制檯輸出日誌資訊 79 print("資料載入完畢!") 80 } 81 82 override func didReceiveMemoryWarning() { 83 super.didReceiveMemoryWarning() 84 // Dispose of any resources that can be recreated. 85 } 86 }