嘗試從網路抓取並顯示圖片
使用 URLSessionDataTask抓資料以及的 JSONDecoder來做分析資料
分析資料有很多種方式來分析,可以使用第三方函式庫來分析,也能使用apple在 swift4中提供的 codable protocol達成,這次不是取很複雜的東西(e.g. 像是影音檔),所以就先不使用第三方函式庫。
首先找個 API,由於要做類似 10 years challenge APP(一種使用很多圖片的 APP),所以就用 Unsplash API,接下來先申請個帳號,申請完按下 New Application
接著要確認一些重要事項,記得打勾
寫上要用在什麼樣子的 APP上
接著就能拿到 key了
拿到 API key之後參考一下文件網址寫法,除了 cliend_id之外其他都是選填, order_by有三種排序方式可以選, latest. oldest. popular, per_page則是可以設定資料數
https://api.unsplash.com/photos/?client_id=YOUR_ACCESS_KEY
&order_by=ORDER&per_page=NUMBER_OF_PHOTOS
接著將網址送出就能拿到結果,可以看到有一堆字
將資料貼在 JSON Editor Online這個網站就能看到資料的結構
我們需要 urls裡的 regular作為圖片連結, created_at作為時間,alt_description作為圖片解釋,user裡面的 first_name當作作者名稱
取得資料之後接下來要先能夠在 xcode上顯示,可以用 URLSessionDataTask來達成,URLSession是使用 thread來做事,會在背景執行,因此不會干擾主要在執行的程式。
從網路上取得JSON資料
先用 URLSession.shared來建立實體以供連線,接著使用 dataTask (with: completionHandler:)來取得(data, response,error)三種資料,資料會傳到閉包裡面,在閉包裡就能分析取得的資料,最後記得要用 resume()執行剛才所指派的任務。
取得資料之後,由於是 JSON格式不會在console上顯示,為了要顯示出來,必須將它轉為 String(使用第4到5行的 String(data: data, encoding: .utf8))。
定義 JSON資料的格式
取得資料後必須分析資料才能拿來使用,分析前必須先將想要取得資料的型別先定義出來,這樣程式在分析時才不會不了解型別導致出錯。
swift4在解析 JSON時要先將 JSON的 Dictionary變成一個自訂的型別,這個型別必須遵守 Codable(代表可以解碼跟編碼)或者 Decodable protocol,最後將 Dictionary中的 key(像是在 Unsplash API中的 create_at)轉換型別。
因為我們要使用上述的四種資料( urls裡的 regular, created_at,alt_description與 user裡面的 first_name ),所以在定義型別時要定義出來,其餘用不到的可以省略。
若 JSON第一層是 array([])與 JSON第一層為 object({})的定義資料型別是相同的方法,差異就只有 array在使用時要加上[],下方就是我定義的型別
宣告後接著就先測試看看是否能將型別套用在網路上抓下來的資料
這邊貼一個抓失敗的例子,錯誤訊息寫說 Expected to decode Array but found a dictionary instead,意思就是原本定義是期望著拿到 Array<Any>的格式,但是在抓資料時卻找到 dictionary,怎麼回事?看一下定義的方法
發現了在 user這邊定義格式為自訂的格式 info Array,但是 info的格式從網頁上看到的是 dictionary,因此必須將代表 Array的 [ ] 拿掉才是正確的。
將 JSON資料轉化成自訂型別 Photos
成功分析 JSON資料後,就能開始嘗試將資料轉化成自訂型別,程式碼與上方定義 JSON格式的程式大同小異,只是多了 JSONDecoder,用來將 JSON格式轉換成 [Photos],加上 [] 是因為資料型態原本就是陣列。
decoder.decode(想要生成的型別,資料) → 這邊使用 .self 來傳入想要生成的型別
DateDecodingStrategy這邊使用國際標準 iso 8601
使用 UIImage從 URL取得照片
最後把 URL從資料裡面取出,將URL經過 URLSession.shared.dataTask取得資料後就能夠使用 UIImage來顯示
最後有出現可怕的紫色問題,所以加上 DispatchQueue.main.async讓程式跑在 main Queue中
結果
Github
參考文章
JSON格式分析
找錯誤