iOS的路徑

專案資料夾內的路徑

利用Bundle.main獲取 可以指定檔案名稱以及副檔名。

// 得到url
let url = Bundle.main.url(forResource: "myjson", withExtension: "json")
// 得到path
let path = Bundle.main.path(forResource: "myjson", ofType: "json")

一般App路徑

Document範例

// 透過路徑尋找URL
let path = NSHomeDirectory() + "/Document"
let urlfrompath = URL(fileURLWithPath: path)

// 直接拿取URL,陣列第0個是資料夾本身(雖然也只有一個url)
let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]

Caches 範例

// 透過路徑尋找URL
let path = NSHomeDirectory() + "/Library/Caches"
let urlfrompath = URL(fileURLWithPath: path)

// 直接拿取URL
let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]

Temp 範例

// 兩種路徑取得的方法
let pathFromNSHome = NSHomeDirectory() + "/tmp"
let pathFromLibrary = NSTemporaryDirectory()

// URL
let urlfrompath = URL(fileURLWithPath: pathFromNSHome)

新增路徑

  1. 將想要新增的路徑名稱寫出來
  2. 利用FileManager.default.createDirectory新增路徑
    • 此方法的withIntermediateDirctories參數若設成true,可以幫你遞迴建立不存在的資料夾
let directoryPath = NSTemporaryDirectory() + "/images"
do{
	try FileManager.default.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil)
}catch{
	print("Cannot create directory")
}

列出某個路徑下的所有檔案

  1. 先找到想列出檔案的路徑
  2. 利用 FileManager.default.contentsOfDirectory來列出此資料夾底下的檔案
let tempPath = NSTemporaryDirectory()
do{
  let fileList = try FileManager.default.contentsOfDirectory(atPath: tempPath)
  for file in fileList{
  	print(file)
  }
}
catch{
	print("Cannot list directory")
}

查看路徑資訊

FileManager.default.fileExists 可以幫你查看這個檔案是否存在,以及該檔案是否為一個Directory。
需要特別注意的是OBJCBool的使用

let path = NSTemporaryDirectory() + "/images"
var isDirectory:ObjCBool = false
let isExist = FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory)
if isExist == true && isDirectory.boolValue == true{
	print("File exist and it is a direcotry")
}
else if isExist == true && isDirectory.boolValue == false{
	print("File exist but it is not a direcotry")
}
else{
	print("File isn't exist")
}

複製貼上刪除檔案

使用下方函式,記得加上do try catch。

FileManager.default.copyItem(atPath: path, toPath: cpPath)
FileManager.default.moveItem(atPath: path, toPath: mvPath)
FileManager.default.removeItem(atPath: path)

一般型別寫檔讀檔

讀寫String

寫檔要呼叫String的方法

let text = "Hello World"
let filePath = NSTemporaryDirectory() + "Text.txt"
do{
	try text.write(toFile: filePath, atomically: true, encoding: .utf8)
}catch{
	print("Not save correctly")
}

讀檔要使用NSString

let filePath = NSTemporaryDirectory() + "Text.txt"
do{
  let loading = try NSString(contentsOfFile: filePath, encoding: String.Encoding.utf8.rawValue)
  print(loading)
}catch{
	print("No save file")
}

讀寫Array

利用NSArray做寫入

let originalArray = ["Apple", "Banana", "MAngo"]
let arrayToSave = NSArray(array: originalArray)
let filePath = NSTemporaryDirectory() + "saveArray.txt"
arrayToSave.write(toFile: filePath, atomically: true)

利用NSArray做讀出

let filePath = NSTemporaryDirectory() + "saveArray.txt"
if let loadArray = NSArray(contentsOfFile: filePath) as? [String]{
	print(loadArray)
}

讀寫Dict

寫入靠NSDictionary

let originalDict = ["1":"apple", "2":"banana", "3":"orange"]
let dictToSave = NSDictionary(dictionary: originalDict)
let filePath = NSTemporaryDirectory() + "saveDict.txt"
dictToSave.write(toFile: filePath, atomically: true)

讀取靠NSDictionary

let filePath = NSTemporaryDirectory() + "saveDict.txt"
  if let loadDict = NSDictionary(contentsOfFile: filePath) as? [String:String]{
  print(loadDict)
}

多媒體寫檔讀檔

圖檔

存檔
多媒體的寫檔只能依靠URL而不能靠檔案路徑。

  1. 先拿到要儲存的UIImage (可靠照相機或手機已有的圖片)
  2. 以指定格式載入圖片 (UIImagePNGRepresentation或UIImageJPGRepresentation)
  3. 產生路徑及URL
  4. 在指定URL下存檔
// 拿到UIImage
guard let image = UIImage(named: "Tails") else {
  print ("Cannot find image")
  return
}

if let dataToSave = UIImagePNGRepresentation(image){
	// 產生路徑
  let filePath = NSTemporaryDirectory() + "savedImage.png"
  let fileURL = URL(fileURLWithPath: filePath)
  // 寫入
  do{
  	try dataToSave.write(to: fileURL)
  }catch{
  	print("Can not save Image")
  }
}

讀檔

  1. 先用UIImage載入
  2. 把載入圖片放在UIImageView上面
let filePath = NSTemporaryDirectory() + "savedImage.png"
let image = UIImage(contentsOfFile: filePath)
myImageView.image = image

自定義class讀寫檔

要寫檔的class必須繼承

  • NSObject
  • NSCoding

並複寫相關function

class Item : NSObject, NSCoding{
    var name:String?
    var detail:String?
    
    init(name:String, detail:String) {
        self.name = name
        self.detail = detail
    }
    
    required init?(coder aDecoder: NSCoder) {       
        name = aDecoder.decodeObject(forKey: "name") as! String
        detail = aDecoder.decodeObject(forKey: "detail") as! String
    }
    
    func encode(with aCoder: NSCoder) {
        aCoder.encode(name, forKey: "name")
        aCoder.encode(detail, forKey: "detail")
    }
}

可以來試著測試了
寫檔

  1. 產生物件
  2. 利用NSKeyedArchiver.archivedData包裹物件,產生data
  3. 找到寫檔路徑
  4. 將data寫入指定路徑
let item = Item(name: "危城", detail: "動作")
let data = NSKeyedArchiver.archivedData(withRootObject: item)
let docUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let url = docUrl.appendingPathComponent("myfile.txt")
try! data.write(to: url)

讀檔

  1. 找到讀檔路徑
  2. 獲取Data
  3. 利用NSKeyedUnarchiver.unarchiveObject,將data轉換成指定物件
let docUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let url = docUrl.appendingPathComponent("myfile.txt")
let data = try? Data(contentsOf: url)

if let data = data {
	let item = NSKeyedUnarchiver.unarchiveObject(with: data) as! Item
	print("=== Read ===")
	print(item.name)
	print(item.detail)
}