#6 用RESTful API來訂杯珍奶喝吧!Part-3-menu呈現及banner輪播

Tai
彼得潘的 Swift iOS / Flutter App 開發教室
11 min readNov 16, 2022

接下來是這個APP的重頭戲,建置飲料menu、訂單的新增、查詢、修改、刪除功能,最花時間也是最重要的部份~請客位看倌耐心欣賞~

先來說說飲料menu建置的部份:

使用Airtable當成遠端資料庫,將飲料的相關資訊建置在其上,使用RESTful API取得資料及上傳資料

  1. 在Airtable上建立2個表單-DrinkingMenuList、OrderList

2. 在Xcode中新增View Controller,加入Navigation Controller及Tab Bar Controller,將Tab Bar項目改成"訂飲料"及購物車圖示

3. 在上面第2點新增的View Controller中放置1個Collection View建置輪播banner、2個Container View、1個Segmented Control及2個Table View Controller製作訂單列表(Segmented Control是用來切換冷熱飲List),並設定好AutoLayout

4. 使用Segmented Control及2個Container View切換冷熱飲畫面,先拉好2個Container View的@IBOutlet Collection及Segmented Control的@IBAction,再來寫切換的function

節錄程式碼如下:

    //將2個Container View拉到@IBOutlet Collection
@IBOutlet var drinkingContainerViews: [UIView]!

//Segmented Control的@IBAction
@IBAction func segmentedControlAction(_ sender: UISegmentedControl) {
//切換冷熱飲
drinkingContainerViewsChange()

}

//切換冷熱飲
func drinkingContainerViewsChange() {
//先將Container View全部設為隱藏
drinkingContainerViews.forEach {
$0.isHidden = true //$0代表傳入的Container View
}
//將選取到的Container View設定為顯示
drinkingContainerViews[segmentedControl.selectedSegmentIndex].isHidden = false
}

5. 將2個Container View原有的View Controller刪除並與2個Table View Controller用Embed的方式連接,在Table View Controller自訂想要的Cell樣式後,新增2個Table View Controller型別檔(及2個Table View Cell型別檔,並指定給Table View Controller及Cell

6. 解析Airtable API的JSON檔


struct MenuList: Codable {
var records: [DrinkingRecords]
}

struct DrinkingRecords: Codable {
var fields: DrinkingDetail
}

struct DrinkingDetail: Codable {
var price: Int
var name: String
var image: [imageDeatil]
var iceHotKind: [String]
var category: String

struct imageDeatil: Codable {
var url: URL
}
}

7. 透過API連線到Airtable取得飲品menu list,API_KEY置換成自己的

let urlString = "https://api.airtable.com/v0/appHy2q9FOUrGGhqS/DrinkingMenuList?api_key=API_KEY"
if let url = URL(string: urlString) {
URLSession.shared.dataTask(with: url) { data, response, error in
if let data {
let decoder = JSONDecoder()
do {
let menuDataList = try decoder.decode(MenuList.self, from: data)
for i in 0...(menuDataList.records.count - 1){
if menuDataList.records[i].fields.iceHotKind[0] == "Ice" {
self.menuList.append(menuDataList.records[i].fields)
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch {
print(error)
}
}
}.resume()
}

8. 取得資料後呈現在APP上的樣子

9. 最後完成banner輪播,需在Assets放置7張一樣大小的圖片(想輪播幾張就放幾張),接下來撰寫程式碼(做法參考:https://youtu.be/rXkemZojlW8)

重點!!! Collection View的Estimate Size設成none及Image View的Content Mode設成Scale To Fill

節錄程式碼如下:

    //Controller conform to protocol
class MainViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout

//控制條件的計數
var imageIndex: Int = 0

//在Assets存了七張圖片,儲存圖片的陣列,因為要看起來一直往左滑動,故在最後補上第一張,才像是無限輪播
let imageArray = ["1", "2", "3", "4", "5", "6", "7", "1"]

//設定代理
photoCarouselCollectionView.delegate = self
photoCarouselCollectionView.dataSource = self

//使用內建時間計數器每2秒換圖
Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(autoPhotoCarousel), userInfo: nil, repeats: true)

//執行自動輪播
@objc func autoPhotoCarousel() {
var indexPath: IndexPath
imageIndex += 1
if imageIndex < imageArray.count {
indexPath = IndexPath(item: imageIndex, section: 0)
photoCarouselCollectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally)
} else {
//當圖片輪播到最後一張將imageIndex歸零,改以沒有動畫回到第一張
imageIndex = 0
indexPath = IndexPath(item: imageIndex, section: 0)
photoCarouselCollectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredHorizontally)
autoPhotoCarousel()
}
}

//回傳1個section
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}

//回傳陣列中的圖片數量
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}

//自定義重用cell
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "\(PhotoCarouselCollectionViewCell.self)", for: indexPath) as! PhotoCarouselCollectionViewCell
cell.photoCarouselImageView.image = UIImage(named: imageArray[indexPath.item])
return cell
}

//取得collection view位置及大小資訊
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return collectionView.bounds.size
}

//Collection View為左右捲動,所以cell左右間距為0
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}

//Collection View為左右捲動,所以cell上下間距為0
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}

夜深了~今天就到這邊吧~下次來談談訂單上傳的部份,謝謝觀賞~

關聯文章:

#4 用RESTful API來訂杯珍奶喝吧!Part-1-畫面及功能簡介 — 重來 就從 APPLE APP 開始吧 — Medium

#5 用RESTful API來訂杯珍奶喝吧!Part-2-Web官網整合介紹 — 重來 就從 APPLE APP 開始吧 — Medium

#7 用RESTful API來訂杯珍奶喝吧!Part-4-訂單上傳及查詢 — 重來 就從 APPLE APP 開始吧 — Medium

#8 用RESTful API來訂杯珍奶喝吧!Part-5-訂單修改及刪除 — 重來 就從 APPLE APP 開始吧 — Medium

--

--

Tai
彼得潘的 Swift iOS / Flutter App 開發教室

跌跌撞撞走了編碼人生的前半段,一切又得重來~但勇敢站起來,決定從 IOS APP 作為下一個人生段的起點,好好的再走他一段編碼人生!