Swift

Swift – 如何在本地端儲存 & 讀取資料

本地端儲存以及讀取資料, Swift 是透過FileManager來做存取以及讀取的動作,本機端資料因為iOS 採用 Sandbox架構的緣故, 可使用來作為讀/存檔案的資料夾為Document。

所以第一步

找到 Document資料夾的 URL

機器設定 : Swift4 + iOS11 +  Xcode9

import Foundation
public extension FileManager {
  static var documentDirectoryURL: URL {
    return try! FileManager.default.url(
      for: .documentDirectory,
      in: .userDomainMask,
      appropriateFor: nil,
      create: false
    )
  }
}

將 documentDirectoryURL用extension包住, 之後便可以使用 FileManager.documentDirectoryURL 來取得該URL路徑

針對Byte格式的本地端儲存&讀取

let mBytes: [UInt8] = [
    240,          159,          152,          184,
    240,          159,          152,          185,
    0b1111_0000,  0b1001_1111,  0b1001_1000,  186,
    0xF0,         0x9F,         0x98,         187
]
//mBytes = 😸😹😺😻
let mDataURL = URL(
    fileURLWithPath: "mByte",
    relativeTo: FileManager.documentDirectoryURL
)
let mData = Data(bytes: mBytes)
// 將資料mData 寫入對應的檔案mDataURL
try mData.write(to: mDataURL)
// 將資料mData 寫入對應的檔案mDataURL, 並給予副檔名
try mData.write(to: mDataURL.appendingPathExtension("txt"))
// 從檔案中取得對應所儲存的資料
let savedMData = try Data(contentsOf: mDataURL)
let savedMBytes = Array(savedMData)

String的本地端儲存&讀取

let string = String(data: savedMData, encoding: .utf8)!
let stringURL =
  FileManager.documentDirectoryURL
  .appendingPathComponent("string")
  .appendingPathExtension("txt")
// 將字串中的資料寫入string.txt儲存
try string.write(to: stringURL, atomically: true, encoding: .utf8)
// 直接透過URL將儲存的檔案讀取出來
try String(contentsOf: stringURL)

 

圖片 Image 的本地端儲存&讀取

有些時候需要將圖片從網路上讀取下來後儲存, 或者資料庫型態的檔案, 無法直接在Bundle.main 底下使用, 這時需要將檔案轉存在 Document中後使用。
如果需要將如下圖 Resources 中的 png 圖檔轉存進Document的話, 可以使用下面的函式。

 

// 在FileManager extension 底下新增函式

static func copyPNGSubdirectoriesToDocumentDirectory(subdirectoryNames: String...) throws {
    for subdirectoryName in subdirectoryNames {
      let documentSubdirectoryURL = URL(
        fileURLWithPath: subdirectoryName,
        relativeTo: FileManager.documentDirectoryURL
      )
      
      //在本地端 Document 底下建立與Resource 相同的資料夾
      try? FileManager.default.createDirectory(
        at: documentSubdirectoryURL,
        withIntermediateDirectories: false
      )
      // 將 Resources 底下的 PNG 取得對應的 URL
      guard let pngURLs = Bundle.main.urls(
        forResourcesWithExtension: "png",
        subdirectory: subdirectoryName
      )
      else {continue}
      
      for pngURL in pngURLs {
        let data = try Data(contentsOf: pngURL)
        try data.write(
          to: documentSubdirectoryURL.appendingPathComponent(pngURL.lastPathComponent),
          options: .atomic
        )
      }

    }
}

 
如果需要取得 Document 中底下的 PNG 圖檔可以使用下面的函式

// 在FileManager extension 底下新增函式
 
static func getPNGFromDocumentDirectory(subdirectoryName: String, imageName: String) -> UIImage? {
    return UIImage(contentsOfFile: FileManager.documentDirectoryURL.appendingPathComponent(subdirectoryName).appendingPathComponent(imageName).appendingPathExtension("png").path)
}

之後便可以用下面的方式直接取得 UIImage 來使用

FileManager.getPNGFromDocumentDirectory(subdirectoryName: "Scenes", imageName: "Forest")

 
Swift 在本地端儲存以及讀取資料, 大多使用 URL的形式後透過 FileManager來使用, 每次做取得動作時, 會有回傳 nil 的情形或者找不到檔案的例外情況, 用 try 以及 ? 來作為檔案格式,  需要特別注意 。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *