使用 google 表單製作 iOS App 開發練習的假資料 array
By: 彼得潘的 Ios App Neverland
Tags: iOS, Xcode, Swift, Swiftui

學習開發 iOS App 時，很多元件都要透過 array 設定顯示的內容，比方 SwiftUI 的 List & ForEach，UIKit 的 table view & collection view。

使用 SwiftUI 的 List 或 UIKit 的 UITableView 呈現的 Christmas 歌單頁面

因此當我們還不會從網路抓資料，學習這些 UI 元件或製作畫面時，我們時常會手動輸入包含假資料的 array，比方以下我們勤勞地輸入每本書的資料。

let books = [

Book(name: "The Mysterious Affair at Styles", published: 1920),

Book(name: "Endless Night", published: 1967),

Book(name: "Crooked House", published: 1948),

Book(name: "Death On The Nile", published: 1937)

]

不過手動輸入實在有點辛苦，有沒有一勞永逸的方法呢？

有的 ! 我們可以在 google 表單儲存一份萬用的資料，包含了畫面呈現需要的文字，圖片等資料，而且更棒的是我們可以輸入自己感興趣的內容，比方貓，蜘蛛人，推理小說，英國之類，這樣練習製作各種畫面時都可以套用，而且寫程式時看到滿滿喜歡的東西，debug 到半夜也不覺累了。

接下來就讓我們一步步說明詳細的步驟吧。

使用 google 表單輸入假資料和產生 JSON

參考以下連結使用 google 表單和產生 JSON。

在此彼得潘輸入最愛的推理小說女王 Agatha Christie 的作品。如下圖所示，imageURL 代表圖片的網址，因此到時候 App 可利用網址抓圖。若想要 App 的圖片來自專案的 assets，則可在 imageName 欄位輸入圖片在 assets 裡的名字。

值得注意的，下方的名稱 Sheet1 將成為 JSON 資料裡的欄位名字。

在此我們將它改成 data。

下載表單產生的 excel 檔。

透過網站 Excel To Json Converter 將 excel 變 JSON。

下載產生的 json 檔。

將 json 檔加到專案的 development assets

將剛剛下載的 JSON 檔放到 development assets，方法可參考以下連結。

在此彼得潘將它加到 Preview Assets.xcassets，命名為 demoData。

定義 JSON 資料對應的型別

demoData 的 JSON 格式如下。

依據上圖的格式定義 JSON 對應的 Decodable 型別。值得注意的，剛剛excel 產生的 JSON 內容都會是字串，所以數字 1920 也會是字串。

struct DemoData: Decodable {

let data: [Book]

} struct Book: Decodable {

let name: String

let published: String

let imageURL: URL

let summary: String



}

還沒學過 JSON 解析的初學者，此步驟可參考以下方法修改。

步驟 1

自訂第二個 struct 的型別名稱，比方資料是電影，所以取名 Movie，{ } 裡的常數名稱依據表單第一列的內容決定，因此我們宣告 5 個常數，分別命名為 name, IMDB, releaseDate, cast & imageURL。常數的型別通常是 String，只有網址要改成 URL

步驟 2

[ ] 裡的型別是我們在步驟 1 定義的名稱，因此改成 Movie。

值得注意的，此處的常數名必須和以下的表單欄位一致，因此我們取名為 data。

宣告將 JSON 資料變成 array 的 static computed property

宣告 static 的 computed property，之後用 Book.data 即可讀取。

extension Book { static var data: [Self] {



if let data = NSDataAsset(name: "demoData")?.data,

let demoData = try? JSONDecoder().decode(DemoData.self, from: data){

return demoData.data

} else {

return []

}

}

}

ps: 此段程式還不太了解的初學者，只要修改兩個地方，將 extension Movie 改成自訂的型別名，比方 extension Book，然後在 NSDataAsset( ) 裡傳入 asset 的名字。

使用 google 表單製作假資料 array 的 4 個步驟

我們可以將剛剛介紹的方法整理成以下 4 個步驟。

使用 google 表單輸入假資料和產生 JSON 將 JSON 檔加到專案的 development assets 定義 JSON 資料對應的型別 宣告將 JSON 資料變成 array 的 static computed property

ps: 若是顯示的圖片來自 Xcode 專案，而不是網路，則要再將圖片放到 Preview Assets。

最後讓我們分別以 SwiftUI & UIKit 為例，示範如何使用剛剛產生的書單 array 製作畫面吧。

SwiftUI 範例

生成畫面 BookList 時傳入 array Book.data ，網路圖片的抓取則透過 SPM 安裝套件 Kingfisher，然後以 KFImage 顯示。

import SwiftUI

import KingfisherSwiftUI struct BookList: View {

var books: [Book]



var body: some View {

List(books, id: \.name) { (book) in



HStack {

KFImage(book.imageURL)

.resizable()

.frame(width: 100, height: 100)

.clipShape(Circle())

VStack(alignment: .leading) {

Text(book.name)

.font(.title)

.layoutPriority(1)

Text(book.published)

Text(book.summary)

.foregroundColor(.secondary)

.lineLimit(3)

}

}

}

}

} struct BookList_Previews: PreviewProvider {

static var previews: some View {

BookList(books: Book.data)

.preferredColorScheme(.dark)

}

}

UIKit 範例

參考以下連結利用 flow layout 的 collection view 製作照片牆。

將 Book.data 存到 BookCollectionViewController 的 property books，網路圖片的抓取則透過 SPM 安裝套件 Kingfisher，然後在 image view 利用 .kf.setImage 傳入網址顯示圖片。

import UIKit

import Kingfisher class BookCollectionViewController: UICollectionViewController {



let books = Book.data



func setupFlowLayout() {

let itemSpace: CGFloat = 3

let columnCount: CGFloat = 2

let inset: CGFloat = 10

let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout

let width = floor((collectionView.bounds.width - itemSpace * (columnCount-1) - inset * 2) / columnCount)

flowLayout?.itemSize = CGSize(width: width, height: width)

flowLayout?.estimatedItemSize = .zero

flowLayout?.minimumInteritemSpacing = itemSpace

flowLayout?.minimumLineSpacing = itemSpace

flowLayout?.sectionInset = UIEdgeInsets(top: 0, left: inset, bottom: 0, right: inset)

}



override func viewDidLoad() {

super.viewDidLoad()



setupFlowLayout()

}



override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

return books.count

}



override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "\(BookCollectionViewCell.self)", for: indexPath) as! BookCollectionViewCell



let book = books[indexPath.item]

cell.imageView.kf.setImage(with: book.imageURL)



return cell

}



}

適合初學者練習的題目

利用此方法產生的 array 學習使用以下元件或製作需要大量假資料的頁面。

SwiftUI 的 List，ScrollView，LazyVGrid & ForEach。

UIKit 從 data source 控制內容的元件，比方 table view，collection view，picker view & UIPageViewController。

One more thing，想練習串接網路 API

可以將 JSON 內容貼到 Mocky 產生 API 的網址。