#21 台灣特有種鳥類列表
有了傑森解碼器之後,我們就不需要將資料寫入程式裡面,而是從外部檔案或網路資料庫讀取資料進來,程式裡面只要定義好 struct 資料結構並確認與 JSON 內容一致即可。
現在我們終於可以列出完整的30種台灣特有種鳥類。
// 2-7b 台灣特有種鳥類
// Created by Heman, 2021/08/18
import PlaygroundSupport
import SwiftUI
struct 鳥類: Codable, Identifiable {
var id: Int
var 中文名: String
var 別名: String
var 科名: String
var 英文名: String
var 圖片檔名: String
var 圖片來源: String
var 攝影者: String
}
func 傑森解碼器(_ 檔名: String) -> [鳥類]? {
if let 檔案 = Bundle.main.url(forResource: 檔名, withExtension: "json") {
do {
let 資料 = try Data(contentsOf: 檔案)
let 結果 = try JSONDecoder().decode([鳥類].self, from: 資料)
return 結果
} catch {
print("error:\(error)")
}
}
return nil
}
let 特有種清單 = 傑森解碼器("2-7 台灣特有種鳥類 - 2021") ?? []
for 鳥種 in 特有種清單 {
print(鳥種.id, 鳥種.中文名, "\t", 鳥種.英文名, "\t", 鳥種.圖片來源)
}
struct 相框: View {
var 檔名: String
init(_ p: String) {
檔名 = p
}
var body: some View {
if 檔名 == "" {
Image(systemName: "camera.circle")
.resizable()
.scaledToFit()
.foregroundColor(.red)
.opacity(0.4)
} else {
Image(uiImage: UIImage(named: 檔名)!)
.resizable()
.scaledToFit()
}
}
}
struct 單項顯示: View {
var 鳥: 鳥類
var body: some View {
HStack {
VStack {
Text(鳥.中文名)
.font(.title)
.foregroundColor(.blue)
ZStack(alignment: .bottomLeading) {
相框(鳥.圖片檔名)
.frame(width: 120)
Text("\(鳥.id)")
.font(.title)
.foregroundColor(.white)
.shadow(color: .black, radius: 2, x: 0, y: 0)
}
}
VStack(alignment: .leading) {
Text("別名:" + 鳥.別名)
Text("科名:" + 鳥.科名)
Text("英文名稱:" + 鳥.英文名)
Text("圖片來源:" + 鳥.圖片來源)
Text("攝影者:" + 鳥.攝影者)
}
.font(.title2)
.lineLimit(1)
} .frame(height: 100)
}
}
struct 台灣特有種鳥類: View {
var body: some View {
VStack {
Rectangle()
.frame(height: 75)
.foregroundColor(.green)
.overlay(Text("台灣特有種鳥類").font(.largeTitle))
ScrollView {
ForEach(特有種清單) { 特有種 in
單項顯示(鳥: 特有種)
.padding()
}
}
}
}
}
PlaygroundPage.current.setLiveView(台灣特有種鳥類())
與前一課2-6b範例比較起來,我們再做最後的兩個修飾:
(1) 「單項顯示」增加一個編號,字體用反白陰影,並以 ZStack 安排在圖片左下角位置
ZStack(alignment: .bottomLeading) {
相框(鳥.圖片檔名)
.frame(width: 120)
Text("\(鳥.id)")
.font(.title)
.foregroundColor(.white)
.shadow(color: .black, radius: 2, x: 0, y: 0)
(2) 螢幕最上方增加「標題」方框
Rectangle()
.frame(height: 75)
.foregroundColor(.green)
.overlay(Text("台灣特有種鳥類").font(.largeTitle))
最後執行的結果如下圖,是不是與一開始的設計框架十分接近?

由於 JSON 檔案("2-7 台灣特有種鳥類 - 2021.json")已經將所有鳥類圖片移除,方便讀者測試,因此會全部顯示系統圖示。
程式最後我們用 ScrollView 來控制螢幕捲動,預設為垂直捲動,可加參數 ScrollView(.horizontal) 改成水平捲動。
ScrollView 也可改為 List,同樣可以往下捲動,但外觀稍有差異,而且 List 還提供一些額外的互動功能,以後有機會再介紹。修改 List 如下影片所示。
註解
這個程式用到的資源比較多,如果遇到程式無法執行(但並非JSON解碼的問題),有可能是Swift Playgrounds本身的問題,可以按「執行我的程式碼」左邊「碼表」符號,將「啟用結果」關閉,如下圖。

預設是「啟用結果」,在「執行我的程式碼」時會追蹤每筆資料變動次數以顯示在程式頁面,這對初學者很有幫助,但因額外使用很多資源,容易造成執行速度變慢,甚至執行中斷。