Documents Directory là một thư mục trong sandbox của ứng dụng iOS được thiết kế để lưu trữ dữ liệu người dùng cần tồn tại giữa các phiên làm việc của ứng dụng và có thể truy cập được qua iTunes File Sharing và iCloud. Theo Apple File System Programming Guide (2024), nội dung của thư mục này tự động được bao gồm trong các bản sao lưu iCloud và iTunes, vì vậy nhà phát triển cần có ý thức lựa chọn dữ liệu nào sẽ đặt trong Documents. Không giống như Caches Directory, các tệp trong Documents không bị hệ thống xóa khi thiếu dung lượng — trách nhiệm quản lý kích thước thuộc về ứng dụng.
Những điểm chính
Documents Directory là một thư mục bên trong sandbox của ứng dụng iOS được thiết kế để lưu trữ dữ liệu người dùng cần tồn tại giữa các lần khởi động và có thể truy cập được. Mỗi ứng dụng có sandbox riêng biệt và Documents là một trong những thư mục chính cùng với Caches, tmp và Library.
iOS sử dụng sandbox nghiêm ngặt: ứng dụng không có quyền truy cập vào hệ thống tệp của các ứng dụng khác hoặc vào các thư mục hệ thống nếu không có quyền đặc biệt. Documents Directory là thư mục duy nhất mà người dùng có thể xem nội dung qua iTunes File Sharing (khi bật khóa UIFileSharingEnabled trong Info.plist).
Theo Apple WWDC 2023, hơn 85% ứng dụng trong App Store sử dụng Documents Directory để lưu trữ ít nhất một loại dữ liệu người dùng — từ PDF đã xuất đến tệp trò chơi đã lưu và hình ảnh đã xuất.
Điều quan trọng là nhà phát triển phải hiểu: các tệp trong Documents được tự động bao gồm trong các bản sao lưu iCloud và iTunes. Nếu ứng dụng lưu trữ khối lượng lớn dữ liệu có thể khôi phục trong Documents (ví dụ: bộ nhớ đệm hình ảnh hoặc tệp tạm thời), điều này dẫn đến tiêu thụ không cần thiết dung lượng lưu trữ iCloud của người dùng.
Trong Swift, đường dẫn đến Documents Directory được lấy qua FileManager. Apple khuyến nghị sử dụng API dựa trên URL thay vì dựa trên chuỗi để tương thích tốt hơn với các khả năng hiện đại của iOS.
import Foundation
let fileManager = FileManager.default
guard let documentsURL = fileManager.urls(
for: .documentDirectory,
in: .userDomainMask
).first else { return }
// Tạo tệp trong Documents
let fileURL = documentsURL.appendingPathComponent("report.pdf")
let data = Data("Hello, world!".utf8)
try data.write(to: fileURL)
Objective-C sử dụng NSSearchPathForDirectoriesInDomains — một cách tiếp cận cũ hơn nhưng vẫn được hỗ trợ, trả về đường dẫn chuỗi thay vì URL.
@import Foundation;
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory,
NSUserDomainMask,
YES
);
NSString *documentsPath = paths.firstObject;
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"report.pdf"];
Các dự án hiện đại trong Swift nên sử dụng FileManager.urls vì phương thức này trả về URL thay vì chuỗi, giúp giảm nguy cơ lỗi mã hóa đường dẫn và làm cho mã an toàn hơn về kiểu dữ liệu.
Documents Directory dành cho dữ liệu do người dùng tạo hoặc người dùng cần một cách rõ ràng. Apple nêu bật một số danh mục phù hợp cho thư mục này.
Tệp mà người dùng tạo hoặc nhập — tài liệu văn bản, PDF, hình ảnh, báo cáo đã xuất, tệp sao lưu. Dữ liệu này có giá trị trực tiếp đối với người dùng và việc mất chúng sẽ rất nghiêm trọng.
Lưu trò chơi, tệp trạng thái ứng dụng, dự án đã xuất — mọi thứ người dùng mong đợi khôi phục sau khi cài đặt lại ứng dụng. Tuy nhiên, đối với dữ liệu quan trọng, nên sử dụng thêm iCloud Key-Value Storage hoặc Core Data với đồng bộ hóa iCloud.
| Loại dữ liệu | Phù hợp với Documents | Thay thế |
|---|---|---|
| PDF và tài liệu văn bản | Có | — |
| Bộ nhớ đệm hình ảnh | Không | Caches Directory |
| Lưu trò chơi | Có | iCloud KVS |
| Nhật ký và dữ liệu gỡ lỗi | Không | Caches hoặc tmp |
| Báo cáo đã xuất | Có | — |
Tiêu chí chính: nếu dữ liệu có thể được tải xuống lại từ mạng hoặc được tạo lại — vị trí của chúng là trong Caches, không phải Documents. Mỗi gigabyte trong Documents là một gigabyte trong bản sao lưu iCloud của người dùng.
iOS tự động bao gồm nội dung của Documents Directory trong các bản sao lưu khi thiết bị được kết nối với iTunes hoặc khi đồng bộ với iCloud. Hành vi này không thể bị tắt ở cấp thư mục — chỉ theo từng tệp thông qua thuộc tính NSURLIsExcludedFromBackupKey.
Bắt đầu từ iOS 5.0, Apple bắt đầu từ chối các ứng dụng lưu trữ khối lượng lớn dữ liệu có thể khôi phục trong Documents. Khuyến nghị của Apple: các tệp có thể tải xuống lại nên được lưu trữ trong Caches Directory với cờ loại trừ sao lưu.
import Foundation
let documentsURL = FileManager.default
.urls(for: .documentDirectory, in: .userDomainMask)
.first!
// Loại trừ tệp khỏi sao lưu iCloud
var resourceValues = URLResourceValues()
resourceValues.isExcludedFromBackup = true
var fileURL = documentsURL.appendingPathComponent("cached_data.json")
try fileURL.setResourceValues(resourceValues)
Đồng bộ hóa iCloud hoạt động qua NSUbiquitousContainer nếu ứng dụng sử dụng iCloud Documents. Trong trường hợp này, các tệp từ Documents Directory tự động được đồng bộ giữa các thiết bị của người dùng. Đối với các ứng dụng không có iCloud, đồng bộ hóa chỉ giới hạn ở sao lưu.
Sự khác biệt giữa Documents và Caches là một trong những quan niệm sai lầm phổ biến nhất ở các nhà phát triển iOS mới bắt đầu. Sự khác biệt chính: hệ thống có thể xóa tệp khỏi Caches bất cứ lúc nào để giải phóng dung lượng, nhưng không bao giờ động đến Documents nếu không có sự cho phép của người dùng.
| Đặc điểm | Documents Directory | Caches Directory |
|---|---|---|
| Sao lưu iCloud | Có (mặc định) | Không |
| Xóa bởi hệ thống | Không bao giờ | Khi thiếu dung lượng |
| iTunes File Sharing | Có (khi bật cờ) | Không |
| Mục đích | Dữ liệu người dùng | Bộ nhớ đệm, dữ liệu tạm thời |
| Khôi phục dữ liệu | Cần khôi phục | Có thể tải xuống lại |
Theo Tài liệu dành cho nhà phát triển Apple (2024), việc sử dụng không đúng cách Documents Directory là một trong những lý do phổ biến khiến ứng dụng bị từ chối trong quá trình xem xét: nếu ứng dụng lưu trữ hơn vài megabyte dữ liệu có thể khôi phục trong Documents, Apple khuyến nghị di chuyển chúng sang Caches hoặc áp dụng NSURLIsExcludedFromBackupKey.
Một quy tắc thực tế: nếu người dùng sẽ buồn khi mất tệp — hãy lưu trữ nó trong Documents. Nếu tệp có thể được tải xuống lại hoặc tạo lại — hãy lưu trữ nó trong Caches.
Các nhà phát triển iOS giàu kinh nghiệm đã xây dựng một số quy tắc giúp tránh các vấn đề với Documents Directory ở tất cả các giai đoạn của vòng đời ứng dụng — từ phát triển đến xuất bản trên App Store.
Thường xuyên kiểm tra kích thước của Documents Directory qua FileManager.enumerator(at:includingPropertiesForKeys:). Nếu kích thước vượt quá 100 MB cho dữ liệu không phải của người dùng — đó là lý do để xem xét lại kiến trúc lưu trữ.
Đối với bất kỳ tệp nào có thể tải xuống lại, hãy đặt isExcludedFromBackup = true. Điều này giảm tải cho bộ nhớ iCloud của người dùng và giảm nguy cơ bị từ chối trong App Review.
Khi thay đổi định dạng dữ liệu trong Documents, hãy lên kế hoạch di chuyển: không xóa tệp cũ cho đến khi bạn chắc chắn rằng tệp mới đã được tạo chính xác. Sử dụng các thư mục con dành riêng cho phiên bản.
import Foundation
let documentsURL = FileManager.default
.urls(for: .documentDirectory, in: .userDomainMask)
.first!
let versionDir = documentsURL.appendingPathComponent("v2")
try FileManager.default.createDirectory(
at: versionDir,
withIntermediateDirectories: true
)
Tuân theo các phương pháp này giúp giảm nguy cơ mất dữ liệu người dùng, giảm kích thước sao lưu iCloud và đơn giản hóa việc xem xét trên App Store.
Câu hỏi thường gặp
Có, qua Files — ứng dụng tích hợp sẵn của iOS từ phiên bản 11. Khi bật khóa UIFileSharingEnabled trong Info.plist, nội dung của Documents Directory hiển thị trong ứng dụng Tệp trong phần "Trên iPhone của tôi". Người dùng có thể xem, sao chép và xóa tệp.
Toàn bộ sandbox của ứng dụng, bao gồm Documents Directory, Caches, tmp và Library, bị xóa hoàn toàn khỏi thiết bị. Các bản sao lưu trong iCloud được giữ lại cho đến khi khôi phục hoặc xóa thủ công. Khi cài đặt lại, ứng dụng bắt đầu với một sandbox sạch.
Sử dụng FileManager.enumerator để duyệt tất cả các tệp trong thư mục và tổng hợp kích thước của chúng. Đối với mỗi tệp, lấy thuộc tính .fileSize qua resourceValues(forKeys:). Thay vào đó, có thể sử dụng URLResourceKey.fileSizeKey và .directoryEnumerationResults.
Theo mặc định, Core Data tạo tệp SQLite trong Library/Application Support, không phải trong Documents. Không khuyến nghị di chuyển cơ sở dữ liệu sang Documents — nó sẽ được bao gồm trong iTunes File Sharing và người dùng có thể vô tình xóa hoặc sửa đổi nó. Ngoại lệ là nếu ứng dụng cấp cho người dùng quyền truy cập dữ liệu một cách rõ ràng qua Core Data.
UIFileSharingEnabled (Application supports iTunes file sharing) là một khóa boolean trong Info.plist. Khi đặt thành YES, người dùng có thể sao chép tệp từ Documents Directory qua iTunes và Files. Thêm khóa vào Info.plist: UIFileSharingEnabled = YES. Chỉ bật nó nếu ứng dụng thực sự tạo tài liệu người dùng.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm