iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
tags: 釣魚術 swift swiftui JSON FileManager

本日開發説明

  • 在配合使用者操作介面時新增內容後,更新 class instance 的資料,打算回寫到原檔案。不過這邊踩到一個限制:不能去修改 Bundle 的檔案的限制。
  • 因此更新後的內容,必須是另外新增的。
  • 另外還需要寫一段偵測使用者是否新增過內容的程式碼判斷。

實作:新增目錄與檔案

  • 原始碼片段
  • 首先定義 manager 是 FileManager.default
  • 透過第 7 行:print(url.path) 以便在開發除錯階段找到電腦上的路徑
  • 新建一個 saved 目錄,用來擺放使用者的新儲存檔案
  • let fileUrl = newFolderUrl.appendingPathComponent("NewSecretLocations.json") 則是根據上述生出來的新目錄下,透過 .appendingPathComponent() 方式來產生加上 NewSecretLocations.json 檔名的 url
  • 後面接著透過 jsonEncoder 將 Codable 資料,轉型變成可以存成 json 檔案的特殊字串
    • self.encodeCoordinate() 則是我另外寫的一隻轉換函數,用來將 CLLocationCoordinate2D 拆解成 latitude 和 longtitude,請看後面一段。

func saveDataToFile()

func saveDataToFile() {
    // Create Dir
    let manager = FileManager.default
    guard let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first else {
        return
    }
    print(url.path)
    let newFolderUrl = url.appendingPathComponent("saved")
    do {
        try manager.createDirectory(at: newFolderUrl, withIntermediateDirectories: true)
    } catch {
        print(error)
    }
    // Create file
    let fileUrl = newFolderUrl.appendingPathComponent("NewSecretLocations.json")
    let jsonEncoder = JSONEncoder()
    jsonEncoder.outputFormatting = .prettyPrinted
    // 需要做 error handling
    do {
        let jsonData = try jsonEncoder.encode(self.encodeCoordinate())
        if let jsonString = String(data: jsonData, encoding: .utf8) {
            print(jsonString)
            //try jsonData.write(to: myLocationFile)
            manager.createFile(atPath: fileUrl.path,
                               contents: jsonData,
                               attributes: [FileAttributeKey.creationDate: Date()])
        }
    } catch {
        print(error)
    }
}

func transferCoordinate()

  • 轉譯 JSON File 內容變成 可以被列舉成 PinLocation 的資料格式
func transferCoordinate() {    // 將目前程式使用中的圖釘清單內新增轉換後的資料
    for pin in self.originLoadData {
        self.locationData.append(
            PinLocation(
                name: pin.name,
                image: pin.image,
                coordinate: CLLocationCoordinate2D(latitude: pin.latitude, longitude: pin.longitude),
                rank: pin.rank)
        )
    }
}

func encodeCoordinate() -> [FishPinAnnotation]

  • 轉譯 PinLocation 的資料格式 變成單純的 JSON
func encodeCoordinate() -> [FishPinAnnotation] {
    var retPins: [FishPinAnnotation] = []
    for pin in self.locationData {
        retPins.append(
            FishPinAnnotation(
                name: pin.name,
                image: pin.image,
                latitude: pin.coordinate.latitude,
                longitude: pin.coordinate.longitude,
                rank: pin.rank)
        )
    }
    return retPins
}

操作結果

  • 將使用者輸入完資料後,預期進行儲存行為的這個函數,放到 Alert 清單的確認選項呼叫中,即完成事件的綁定

參考

  1. developer.apple.com - FileManager
  2. developer.apple.com - fileExists(atPath:isDirectory:)

上一篇
【Day 19】Swift 存取 JSON 檔案 - 使用 Codable 和 JSON
下一篇
【Day 21】Bundle Conatiner 和 Application Container
系列文
無法成為釣魚大師也要努力摸魚!!辣個吃魚神器 APP38
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言