Swift小練習 #13 JSON格式-寶可夢圖鑑
製作動機:練習 Json 格式的文件串接,結合 UITableView來製作表格。
問題一:如何獲得 JSON 的檔案
網路上有好心人提供寶可夢資料的各種 API,我們這次練習的是最基本的 JSON 格式文件,以下提供好心網站。
獲取 JSON 文件的方法參照下方教學連結。
並且依照相同方式即可將文件導入至 Xcode,這邊我在過程中遇到了一個小問題,就是放在 assets 中的 json 文件有一個副檔名 .json,但卻因為這個副檔名讀不到資料,害我研究了老半天倒底哪裡打錯了,所以如果有遇到類似狀況可以看看是不是副檔名的問題。
問題二:如何解析 JSON 格式
上面連結已經有教學如何將文件導入了,我們稍微看一下這次的範例內容。
{"id":1,"name":{"en":"Bulbasaur","zh":"妙蛙種子"},"types":{"en":["grass","poison"],"zh":["草","毒"]},"genera":{"en":"Seed Pokémon","zh":"種子寶可夢"},"entries":{"en":["A strange seed was planted on its back at birth. The plant sprouts and grows with this Pokémon.","It can go for days without eating a single morsel. In the bulb on its back, it stores energy.","The seed on its back is filled with nutrients. The seed grows steadily larger as its body grows."],"zh":["背上的種子裡存著很多營養,所以就算好幾天不吃東西也能活得好好的!","從出生的時候開始背上就有一顆植物種子。這顆種子會漸漸地長大。","在出生後的一段時間內,牠會吸收背上種子裡儲存著的營養成長。"]}}
在建立 Model 時,我們必須先找到他矩陣的規律,以建立各種屬性,故我們這邊的範例就把矩陣內的第一個項目拿出來看裡面有哪些東西。
這邊看到裡面有五種屬性,id、name、types、genera、entries,屬性裡面可能又包含了中英文兩種屬性,內容也有可能會是另一個矩陣,所以我們創建的 Model 如下。
struct Pokemon: Decodable {
let id: Int
let name: Name
let types: Types
let genera: Genera
let entries: Entries
}
struct Name: Decodable {
let en: String
let zh: String
}
struct Types: Decodable {
let en: [String]
let zh: [String]
}
struct Genera: Decodable {
let en: String
let zh: String
}
struct Entries: Decodable {
let en: [String]
let zh: [String]
}
如果懶得自己打,可以請 AI 協助,方便省事。
問題三:導入TableViewCell 中
這邊之前已經多次提過 TableView 的設定,故就不再贅述,需要留意一點是,這次的數量較為龐大,一共有九百多筆的 Cell 會產生,故會遇到重複利用而導致的缺點,即是重複拿來用的 Cell 會殘留紀錄到之前的資料。
會遇到這樣情況的是兩個內容為矩陣的屬性,Types 以及 Entries。
因為矩陣的內容我們不曉得每一個裡面的數量究竟為多少,先給大家看一下原本我打得錯誤示範。
for j in 0...entriesCount-1{
let entriesCount = pokemon[indexPath.row].entries.zh.count
cell.pokemonInfo.text! += pokemon[indexPath.row].entries.zh[j]
}
若是一開始這樣執行的話其實還是能跑,前面的資料也都不會有什麼問題,但是一但開始進入 Cell 的重複利用之後,立面的內容將會開始包含前面的資料,並且一直串連下去,變成一個混合錯誤資訊。
於是就試著更改為下列的做法。
let entriesCount = pokemon[indexPath.row].entries.zh.count
var indexEntriesRow = ""
for j in 0...entriesCount-1{
indexEntriesRow += pokemon[indexPath.row].entries.zh[j]
}
cell.pokemonInfo.text! = indexEntriesRow
先建立一個空字串的變數,並且重新將文字放進去,最後再讓 Label 印出即可解決資料重複的問題,這個問題應該跟是本次練習中的一大收穫。
問題四:隨著內容控制高度的 Cell
因為前面遇到了資料混合的這個 Bug,所以導致資料變得非常龐大,一開始沒有認真看以為他們的說明真的多到 Cell 的高度無法負荷了,但是前面的又沒有這麼長,所以就嘗試了 auto layout 。
因為只是要來解決高度的問題,所以我只拉了上面寶可夢名稱以及下面說明的兩個 Label 的 auto layout 而已,拉完後即使不去屬性修改器那邊設定 cell 的高度,實際執行時便會自動依照內容幫你調整高度了。
以上為這次的小練習紀錄。
製作時間約: 1 Day