Swift 操作檔案的VC - UIDocumentPickerViewController

更新於 發佈於 閱讀時間約 10 分鐘

一樣先來看官方文件

A view controller that provides access to documents or destinations outside your app’s sandbox.

其實就是讓你去讀取檔案App的東西

iphone裡的檔案App

iphone裡的檔案App

有兩種模式,Don’t copy the document if you can avoid it. 原則上是不需要就不要特別copy一份:

  1. 打開檔案:可以選擇存取原本的檔案或是copy一份來修改,讓你不會動到原本的檔案。
  2. 輸出到指定位置:指定檔案移到目的地,也可以選擇改變原本的檔案,或是copy一份來修改。

Init的方法

也分兩種(四種?)

打開檔案:操作原本/copy的檔案

  • init(forOpeningContentTypes: [UTType])Creates and returns a document picker that can open the types of documents you specify.
  • init(forOpeningContentTypes: [UTType], asCopy: Bool)Creates and returns a document picker that can open or copy the types of documents you specify.
使用這兩個需先 import UniformTypeIdentifiers,不然會有錯誤

輸出到指定位置:操作原本/copy的檔案

  • init(forExporting: [URL])Creates and returns a document picker that can export the types of documents you specify.
  • init(forExporting: [URL], asCopy: Bool)Creates and returns a document picker that can export or copy the types of documents you specify.

下面的範例都是用第一種forOpeningContentTypes來講。

操作原本檔案需要權限

選擇操作原本檔案,開始存取前,需加上 url.startAccessingSecurityScopedResource(),結束操作後url.stopAccessingSecurityScopedResource()

如果操作原本的檔案又沒加上權限,會取不到檔案。

使用init(forOpeningContentTypes: [UTType])瀏覽檔案

// 打開documentPicker 
@IBAction func openFile(_ sender: UIButton) {
let documenPickerVC = UIDocumentPickerViewController(forOpeningContentTypes: [.content])
documenPickerVC.delegate = self
self.present(documenPickerVC, animated: true)
}

❌ 沒有加上權限存取,讀不到檔案。這邊注意一定要用實機測試,模擬器兩種都不需要權限,會讓你以為天下太平= =

extension ViewController: UIDocumentPickerDelegate {
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
do {
for url in urls {
// 直接操作檔案
let filename = url.lastPathComponent
let resourceValue = try url.resourceValues(forKeys: [.fileSizeKey])
filenameLabel.text = "檔案名稱:\(filename)"
fileSizeLabel.text = "檔案大小:\(resourceValue.fileSize ?? 0)"
}
} catch {
print(error.localizedDescription)
}
}
}
取不到檔案內容

取不到檔案內容

The file “ppt檔.pptx” couldn’t be opened because you don’t have permission to view it.

✅正確的寫法

extension ViewController: UIDocumentPickerDelegate {
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
do {
for url in urls {
    let accessing = url.startAccessingSecurityScopedResource()
     defer {
if accessing {
url.stopAccessingSecurityScopedResource( }
}
// ....操作檔案

另外,有打開權限就要關掉,沒關掉的會可能會造成leak,之後app就沒辦法在存取檔案裡的東西,除非重開。所以最佳寫法就是stopAccessingSecurityScopedResource寫在defer {},跑完一定會關掉。

拿到正確的檔案資訊

拿到正確的檔案資訊

copy的不需要額外權限

使用init(forOpeningContentTypes: [UTType], asCopy: Bool)copy一份的方式瀏覽檔案

// 打開documentPicker 
@IBAction func openFile(_ sender: UIButton) {
let documenPickerVC = UIDocumentPickerViewController(forOpeningContentTypes: [.content], asCopy: true)
documenPickerVC.delegate = self
self.present(documenPickerVC, animated: true)
}

✅ 直接操作檔案

extension ViewController: UIDocumentPickerDelegate {
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
do {
for url in urls {
// 直接操作檔案
let filename = url.lastPathComponent
let resourceValue = try url.resourceValues(forKeys: [.fileSizeKey])
filenameLabel.text = "檔案名稱:\(filename)"
fileSizeLabel.text = "檔案大小:\(resourceValue.fileSize ?? 0)"
}
} catch {
print(error.localizedDescription)
}
}
}
拿到正確的資訊

拿到正確的資訊

我個人偏好跟官方講的一樣,如果沒有特殊需求直接操作原本的檔案就好,不會想要再copy一份,雖然copy方式code比較少😂

UTType

forOpeningContentTypes: [UTType]這個參數,可以讓你限制使用者可以選擇的檔案,不能選擇的會泛灰不能點選,但這東西我覺得極為難用。

因為有被他收編的很輕易就可以寫出來,例如:.jpeg, .png,輕鬆優雅的寫在UTType array裡。

let documenPickerVC = UIDocumentPickerViewController(forOpeningContentTypes: [.jpeg, .png])


但沒被他收編的。例如:微軟word檔、ppt檔。需要自己去找對照表id轉成UTType,非常醜且可怕,而且對照表還莫名的很難搜尋到。

let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [UTType("com.microsoft.powerpoint.ppt")!, UTType("com.microsoft.word.doc")!])


好在iOS14之後他出了一個比較優雅的做法,用fileExtension去判斷type。不過如果使用者亂改副檔名的話,這個判斷結果可能會失準,需自行斟酌。

let acceptTypes = [UTType(filenameExtension: "ppt"), UTType(filenameExtension: "doc")].compactMap{$0}
let documenPickerVC = UIDocumentPickerViewController(forOpeningContentTypes: acceptTypes)



留言
avatar-img
留言分享你的想法!
avatar-img
Michelle Chen的沙龍
8會員
34內容數
紀錄iOS開發上遇到的問題或是一些流程筆記。主要都是Swift。
Michelle Chen的沙龍的其他內容
2024/09/06
本文介紹了使用KeyboardLayoutGuide的方法,以及在不同iOS版本和設備上遇到的佈局問題。透過調整TextView的底部對齊方式,成功解決了在模擬器和真實設備上出現的錯誤,提供了有用的建議給開發者。本文還探討了為何在iOS15與Xib的組合使用中會出現問題,以及解決方案。
Thumbnail
2024/09/06
本文介紹了使用KeyboardLayoutGuide的方法,以及在不同iOS版本和設備上遇到的佈局問題。透過調整TextView的底部對齊方式,成功解決了在模擬器和真實設備上出現的錯誤,提供了有用的建議給開發者。本文還探討了為何在iOS15與Xib的組合使用中會出現問題,以及解決方案。
Thumbnail
2024/08/07
使用者回報的超級奇怪線上問題,用數字鍵盤(NumberPad)更改欄位時,送出後尾數都會消失。例如:30 ⭢ 3,52 ⭢ 5。 尋尋覓覓了兩天終於被我找到這篇,apple的奇葩的bug 重現條件 iOS17 手機設定是繁體中文語系 前一個用過的鍵盤是Cangjie倉頡 or Suchen
2024/08/07
使用者回報的超級奇怪線上問題,用數字鍵盤(NumberPad)更改欄位時,送出後尾數都會消失。例如:30 ⭢ 3,52 ⭢ 5。 尋尋覓覓了兩天終於被我找到這篇,apple的奇葩的bug 重現條件 iOS17 手機設定是繁體中文語系 前一個用過的鍵盤是Cangjie倉頡 or Suchen
2024/07/03
這篇文章探討瞭如何在iOS應用程式中客製化Alert,包括改變字體大小、內嵌連結以及讓Alert的高度隨著字數增長並提供scroll操作。同時使用SwiftUI進行客製化,並介紹瞭解決高度超出範圍後文字捲動與scrollView固定高度的方法。
Thumbnail
2024/07/03
這篇文章探討瞭如何在iOS應用程式中客製化Alert,包括改變字體大小、內嵌連結以及讓Alert的高度隨著字數增長並提供scroll操作。同時使用SwiftUI進行客製化,並介紹瞭解決高度超出範圍後文字捲動與scrollView固定高度的方法。
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
本章節介紹了如何建立並設置Swift項目以及如何選擇和設置Swift代碼編輯器。這包括在Xcode和命令行中建立Swift項目,選擇Xcode、Visual Studio Code或AppCode作為編輯器,以及如何使用SPM安裝插件。
Thumbnail
本章節介紹了如何建立並設置Swift項目以及如何選擇和設置Swift代碼編輯器。這包括在Xcode和命令行中建立Swift項目,選擇Xcode、Visual Studio Code或AppCode作為編輯器,以及如何使用SPM安裝插件。
Thumbnail
Part.1 搞定基本的 UI 開始開發 iOS App。 首先準備一台 Mac,然後安裝 Xcode,新增專案,系統即刻生成基本的專案結構。coding 的起點在檔案 ContentView.swift: import SwiftUI struct ContentView: View {  
Thumbnail
Part.1 搞定基本的 UI 開始開發 iOS App。 首先準備一台 Mac,然後安裝 Xcode,新增專案,系統即刻生成基本的專案結構。coding 的起點在檔案 ContentView.swift: import SwiftUI struct ContentView: View {  
Thumbnail
Sandbox 架構 /Documents:主要用於儲存用戶生成的數據或者不能重新創建的數據。這些可能包括由你的應用程式創建的文件、從服務器下載的文件、用戶在應用程式中創建或修改的數據等。 這些數據在應用程式的生命週期中是持久保存的,即使應用程式被終止或者系統重啟,這些數據也會保留。此外
Thumbnail
Sandbox 架構 /Documents:主要用於儲存用戶生成的數據或者不能重新創建的數據。這些可能包括由你的應用程式創建的文件、從服務器下載的文件、用戶在應用程式中創建或修改的數據等。 這些數據在應用程式的生命週期中是持久保存的,即使應用程式被終止或者系統重啟,這些數據也會保留。此外
Thumbnail
檔案存取 路徑與檔案處理是很常用的功能,他們可以獨立運作,但是常常搭配一起使用,如果你處理的檔案是在當下的目錄,可以不需要使用路徑的功能單獨讀寫檔案,如果是想要做一些資料夾的管理,就需要理解路徑和檔案之間的關係。
Thumbnail
檔案存取 路徑與檔案處理是很常用的功能,他們可以獨立運作,但是常常搭配一起使用,如果你處理的檔案是在當下的目錄,可以不需要使用路徑的功能單獨讀寫檔案,如果是想要做一些資料夾的管理,就需要理解路徑和檔案之間的關係。
Thumbnail
一樣先來看官方文件 A view controller that provides access to documents or destinations outside your app’s sandbox. 其實就是讓你去讀取檔案App的東西 有兩種模式,Don’t copy the do
Thumbnail
一樣先來看官方文件 A view controller that provides access to documents or destinations outside your app’s sandbox. 其實就是讓你去讀取檔案App的東西 有兩種模式,Don’t copy the do
Thumbnail
在第十四課中,我們將探討 Python 中的檔案操作,包括如何讀取、寫入和管理文件。這對於許多實際應用場景都是必要的,例如日誌記錄、資料分析和資料持久化。
Thumbnail
在第十四課中,我們將探討 Python 中的檔案操作,包括如何讀取、寫入和管理文件。這對於許多實際應用場景都是必要的,例如日誌記錄、資料分析和資料持久化。
Thumbnail
  在寫程式過程中時常會使用檔案的讀取、建立、寫入與刪除相關使用,因此這篇就來分享圖片檔案、文字檔案、INI的設定檔案的相關使用。
Thumbnail
  在寫程式過程中時常會使用檔案的讀取、建立、寫入與刪除相關使用,因此這篇就來分享圖片檔案、文字檔案、INI的設定檔案的相關使用。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News