【App Dev-SwiftUI心得筆記】#3 以AirTable作為簡單資料庫進行串連API

Shin Yulin
7 min readMay 21, 2021

--

Goal: 完成Category Art頁面

Used Tools:

AirTable / URLSession / SDWebimage

製作Category DataBase

在AirTable建立簡易的資料庫,並獲取API格式

建立解析JSON用的protocol型別

使用URLSession 獲取Data,進行JSON解析

將解析後的資料顯示在畫免上

SDWebimage → 用來設定顯示網路上圖片的Library

顯示結果

成功畫面/解析失敗畫面

Clean Code!

DateFromAirtable

struct AirtableRecords:Decodable {
var records : [AirTableRecord]
}
struct AirTableRecord: Decodable,Hashable {
var id : String
var fields : Place
}

struct Place: Decodable,Hashable {
var name,thumbnail : String
}

ActiveIndicatorView

import SwiftUIstruct ActiveIndicatorView: UIViewRepresentable {  //製作UIKIT物件
func makeUIView(context: Context) -> UIActivityIndicatorView {
let aiv = UIActivityIndicatorView(style: .large)
aiv.startAnimating()
aiv.color = UIColor.white
return aiv
}

func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {
}

typealias UIViewType = UIActivityIndicatorView


}
struct ActiveIndicatorView_Previews: PreviewProvider {
static var previews: some View {
ActiveIndicatorView()
}
}

CategoryDetialView

import SwiftUIimport SDWebImageSwiftUIclass CaregoryDetialViewModle: ObservableObject {

@Published var isLoading = true///宣告isLoading 狀態 預設為true
@Published var arts = [AirTableRecord]()
@Published var errorMesage = ""
init(){



DispatchQueue.main.asyncAfter(deadline: .now() + 2){

self.isLoading = false
guard let url = URL(string: "<https://api.airtable.com/v0/appUJv9kyMlHpugJ7/Art>") else {
return
}

var request = URLRequest(url: url)
request.setValue("AirTable授權碼", forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) { data, resp, err in

guard let data = data else { return }
do{
let reords = try JSONDecoder().decode(AirtableRecords.self, from: data)
self.arts = reords.records
}
catch{

print("Failed to decode JSON",error)
self.errorMesage = error.localizedDescription
}
}.resume()
}

}

}
struct CategoryDetialView: View {

@ObservedObject var vm = CaregoryDetialViewModle() /// 宣告VM

var body: some View{

if vm.isLoading == true{
VStack{
ActiveIndicatorView()
Text("loading")
.font(.system(size: 12, weight: .semibold))
.foregroundColor(.white)
}
.padding()
.background(Color.black)
.cornerRadius(6)

}else{

ZStack{
Text(vm.errorMesage)
ScrollView(.vertical){
VStack(spacing: 12){
ForEach(vm.arts, id: \\.self) { art in
VStack{
WebImage(url: URL(string: art.fields.thumbnail))
.resizable()
.scaledToFill()
.clipped()
.frame(height: 200)

HStack{
Text(art.fields.name)
.font(.system(size: 14, weight: .semibold))
Spacer()
}
.padding()
.background(Color.white)

}

.asTile()
}
}.padding(.horizontal)
.padding(.top)

}
}
.navigationBarTitle("Category", displayMode: .inline)
}

}
}
struct CategoryDetialView_Previews: PreviewProvider {
static var previews: some View {
NavigationView{
CategoryDetialView()
}
}
}

--

--

Shin Yulin
Shin Yulin

Written by Shin Yulin

一個在前往 iOS 工程世界的視覺工作者

No responses yet