iT邦幫忙

2022 iThome 鐵人賽

0
tags: 釣魚術 swift

前言

  • 最近我將手機更新到 iOS 16 之後,發現我新增用來測試的資料,在刷進改版後的 App 後,資料並不會被重置。(先前儲存到手機的 json)
  • 熊熊想起,如果有人不小心新增錯的資訊,想自刪就刪不掉,尷尬

    原來是被遺忘的刪除功能,少了這個功能,就沒辦法刪除陳永仁的資料...

開發前的簡單想法

  • 在地圖畫面上,弄一個刪除按鈕出來
  • 按下按鈕後跳出 List 選單,秀出那些圖釘名稱
  • 在名稱右邊要有個小按鈕,按下去之後啟動刪除程序
    • 刪除程序,現在要考慮三個部分:運行在記憶體裡的變數、存在手機裡的檔案、畫面呈現的資料
    • (未來要考慮同步到雲上,有網路和沒網路的情況)
      1. 從 locationLoader.locationData 中移除資料
      2. 存回檔案裡 (json)
      3. 從檔案裡再撈回畫面
  • 如果有開發過畫面資料是透過 iteration 產生出來的,一邊迭代一邊砍資料可能會有意想不到的怪事發生。
    • 在我實作的過程中,確實有遇到可怕的事情。後面會寫。

實作細節記錄

  • 首先,從我們先前開發過的畫面,多放一個按鈕就好。
    HStack {    // 刪除釣點
        Spacer()
        Button(action: delSecretLocation) {
            Label("", systemImage: "bin.xmark.fill")
            .labelStyle(.iconOnly)
            .frame(width: 40, height:40)
            .foregroundColor(.white)
            .background(Color.red)
            .cornerRadius(15)
            .padding(10)
        }
    }
    
  • action: delSecretLocation 這個函式,還沒實作,所以要先做一個 func delSecretLocation 在這個 View 裏。
  • 單按鈕按下後,要跳出一個 List 狀的外觀。
    • 先把這個畫面刻好,我把它寫成 DelPinAlert
    VStack {
        Text(boxTitle)
            .font(.title2)
            .fontWeight(.semibold)
        ScrollView(.vertical) {
            LazyVStack {
                ForEach(Array(self.locationLoader.encodeCoordinate().enumerated()), id: \.element) { index, item in
                    HStack {
                        Text(item.name)
                            .frame(alignment: .leading)
                            .font(.headline)
                        Spacer()
                        Button {
                            delSingleLocation(pin: item, index: index)
                        } label: {
                            Label("", systemImage: "xmark.bin.circle")
                                .labelStyle(.iconOnly)
                                .frame(width: 20, height:20)
                                .foregroundColor(.white)
                                .cornerRadius(5)
                                .padding(10)
                        }
                    }
                }
            }
        }
    }
    .padding()
    .frame(width: screenSize.width * 0.6, height: screenSize.height * 0.4)
    .background(Color.indigo)
    .clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous))
    .shadow(color: Color.gray, radius: 15, x: -1, y: -1)
    .offset(y: alertIsPresented ? screenSize.height * 0.1 : screenSize.height)
    
  • 然後弄一個狀態,偵測這顆刪除功能按鈕是否按下?顯示、隱藏、顯示、隱藏...
    func delSecretLocation() {
        self.delLocationListIsPresented.toggle()
    }
    
  • 這剛剛提到的那個函式,每按一下後調整 delLocationListIsPresented 布林變數的狀態。
  • 接著,在畫面中,放置 DelPinAlert
    DelPinAlert(alertIsPresented: $delLocationListIsPresented,
                locationLoader: $myLocationLoader)
    
  • 把顯示與否,以及 locationLoader 兩個東東,傳過去 DelPinAlert 這個 View
  • 接著在 DelPinAlert 中,製作一個新的 function 叫 delSingleLocation,用意是,當傳進所有圖釘資料和索引後,從中刪除指定索引。
func delSingleLocation(pin: FishPinAnnotation, index: Int) {
    self.locationLoader.locationData.remove(at: index)
    self.locationLoader.saveAndReloadLocation()
    self.alertIsPresented.toggle()
}

可能會出錯的地方

  • 上面的做法直接根據索引的數值砍資料喔
  • 這是非常明確指出一定會有某個項次的資料在 Array 中
  • 原本砍資料後,畫面沒有重新載入,所以那些刪除按鈕還存在於畫面中
  • 如果我多按了幾下,運氣好有砍到東西,使陣列越來越短;運氣不好時,砍到不存在的內容,那 App 就會 crush 掉
  • 我目前的做法:砍一筆資料後,就把這個清單收起來,之後要再砍東西,就再按一下紅紅的那顆按鈕叫出清單,這樣他的資料就會是新的。

心得

  • 或許還有更好的做法,等我想到了,我會來改善操作流程。
  • 不過在缺少使用者回饋的情況下,就是我自己想象出來的操作,或許不直覺。

上一篇
【Day 35】集郵冊:透過 ActionSheet 選擇引入照片方式
下一篇
【Day 37】集郵冊:完成郵票設計 / 研究如何以 AWS Amplify 儲存圖片環境
系列文
無法成為釣魚大師也要努力摸魚!!辣個吃魚神器 APP38
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言