Documents Directory คือไดเรกทอรีในแซนด์บ็อกซ์ของแอป iOS ที่ออกแบบมาเพื่อจัดเก็บข้อมูลผู้ใช้ที่ควรคงอยู่ระหว่างเซสชันการทำงานของแอปและสามารถเข้าถึงได้โดยผู้ใช้ผ่าน iTunes File Sharing และ iCloud ตาม Apple File System Programming Guide (2024) เนื้อหาของไดเรกทอรีนี้จะถูกรวมอยู่ในการสำรองข้อมูล iCloud และ iTunes โดยอัตโนมัติ ดังนั้นนักพัฒนาจึงต้องเลือกอย่างมีสติว่าข้อมูลใดจะวางใน Documents แตกต่างจาก Caches Directory ไฟล์ใน Documents จะไม่ถูกลบโดยระบบเมื่อพื้นที่ไม่เพียงพอ — ความรับผิดชอบในการจัดการขนาดตกอยู่ที่แอปพลิเคชัน
ประเด็นสำคัญ
Documents Directory คือไดเรกทอรีภายในแซนด์บ็อกซ์ของแอป iOS ที่ออกแบบมาเพื่อจัดเก็บข้อมูลผู้ใช้ที่ควรคงอยู่ระหว่างการเปิดใช้งานและสามารถเข้าถึงได้โดยผู้ใช้ แต่ละแอปได้รับแซนด์บ็อกซ์ที่แยกเป็นสัดส่วนของตัวเอง และ Documents เป็นหนึ่งในไดเรกทอรีหลักควบคู่ไปกับ Caches, tmp และ Library
iOS ใช้ แซนด์บ็อกซ์ ที่เข้มงวด: แอปไม่สามารถเข้าถึงระบบไฟล์ของแอปอื่นหรือไดเรกทอรีระบบได้หากไม่ได้รับอนุญาตพิเศษ Documents Directory เป็นไดเรกทอรีเดียวที่ผู้ใช้สามารถดูเนื้อหาผ่าน iTunes File Sharing (เมื่อเปิดใช้คีย์ UIFileSharingEnabled ใน Info.plist)
ตาม Apple WWDC 2023 แอปมากกว่า 85% ใน App Store ใช้ Documents Directory เพื่อจัดเก็บข้อมูลผู้ใช้อย่างน้อยหนึ่งประเภท — ตั้งแต่ PDF ที่ส่งออกไปจนถึงไฟล์เกมที่บันทึกไว้และรูปภาพที่ส่งออก
เป็นสิ่งสำคัญที่นักพัฒนาจะต้องเข้าใจ: ไฟล์ใน Documents จะ ถูกรวมโดยอัตโนมัติ ในการสำรองข้อมูล iCloud และ iTunes หากแอปจัดเก็บข้อมูลที่สามารถกู้คืนได้ปริมาณมากใน Documents (เช่น แคชรูปภาพหรือไฟล์ชั่วคราว) สิ่งนี้จะนำไปสู่การใช้พื้นที่จัดเก็บ iCloud ของผู้ใช้โดยไม่จำเป็น
ใน Swift พาธไปยัง Documents Directory ได้รับผ่าน FileManager Apple แนะนำให้ใช้ API ที่ใช้ URL แทนที่จะใช้สตริงเพื่อความเข้ากันได้ดีขึ้นกับความสามารถสมัยใหม่ของ iOS
import Foundation
let fileManager = FileManager.default
guard let documentsURL = fileManager.urls(
for: .documentDirectory,
in: .userDomainMask
).first else { return }
// สร้างไฟล์ใน Documents
let fileURL = documentsURL.appendingPathComponent("report.pdf")
let data = Data("Hello, world!".utf8)
try data.write(to: fileURL)
Objective-C ใช้ NSSearchPathForDirectoriesInDomains — วิธีการที่เก่ากว่าแต่ยังคงรองรับ ซึ่งส่งคืนพาธแบบสตริงแทน URL
@import Foundation;
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory,
NSUserDomainMask,
YES
);
NSString *documentsPath = paths.firstObject;
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"report.pdf"];
โปรเจกต์สมัยใหม่ใน Swift ควรใช้ FileManager.urls เนื่องจากวิธีการนี้ส่งคืน URL แทนที่จะเป็นสตริง ซึ่งช่วยลดความเสี่ยงของข้อผิดพลาดในการเข้ารหัสพาธและทำให้โค้ดปลอดภัยต่อชนิดมากขึ้น
Documents Directory มีไว้สำหรับข้อมูลที่สร้างโดยผู้ใช้หรือที่ผู้ใช้ต้องการอย่างชัดเจน Apple เน้นหลายหมวดหมู่ที่เหมาะสมสำหรับไดเรกทอรีนี้
ไฟล์ ที่ผู้ใช้สร้างหรือนำเข้า — เอกสารข้อความ, PDF, รูปภาพ, รายงานที่ส่งออก, ไฟล์สำรองข้อมูล ข้อมูลนี้มีค่าโดยตรงต่อผู้ใช้และการสูญเสียข้อมูลนั้นจะร้ายแรง
การบันทึก เกม, ไฟล์สถานะแอป, โปรเจกต์ที่ส่งออก — ทุกสิ่งที่ผู้ใช้คาดหวังจะกู้คืนหลังจากติดตั้งแอปใหม่ อย่างไรก็ตาม สำหรับข้อมูลที่สำคัญ แนะนำให้ใช้ iCloud Key-Value Storage หรือ Core Data ที่มีการซิงค์ iCloud เพิ่มเติม
| ประเภทข้อมูล | เหมาะสมสำหรับ Documents | ทางเลือก |
|---|---|---|
| PDF และเอกสารข้อความ | ใช่ | — |
| แคช รูปภาพ | ไม่ | Caches Directory |
| การบันทึก เกม | ใช่ | iCloud KVS |
| บันทึก และข้อมูลดีบัก | ไม่ | Caches หรือ tmp |
| รายงาน ที่ส่งออก | ใช่ | — |
เกณฑ์สำคัญ: หากข้อมูลสามารถดาวน์โหลดซ้ำจากเครือข่ายหรือสร้างใหม่ได้ — ข้อมูลนั้นควรอยู่ใน Caches ไม่ใช่ Documents ทุกกิกะไบต์ใน Documents คือกิกะไบต์ในการสำรองข้อมูล iCloud ของผู้ใช้
iOS จะรวมเนื้อหาของ Documents Directory ในการสำรองข้อมูลโดยอัตโนมัติเมื่ออุปกรณ์เชื่อมต่อกับ iTunes หรือเมื่อซิงค์กับ iCloud พฤติกรรมนี้ไม่สามารถปิดใช้งานในระดับไดเรกทอรีได้ — ทำได้เฉพาะไฟล์ต่อไฟล์ผ่านแอตทริบิวต์ NSURLIsExcludedFromBackupKey
เริ่มจาก iOS 5.0 Apple เริ่มปฏิเสธแอปที่จัดเก็บข้อมูลที่สามารถกู้คืนได้ปริมาณมากใน Documents คำแนะนำของ Apple: ไฟล์ที่สามารถดาวน์โหลดซ้ำได้ควรเก็บไว้ใน Caches Directory โดยมีแฟล็กยกเว้นการสำรองข้อมูล
import Foundation
let documentsURL = FileManager.default
.urls(for: .documentDirectory, in: .userDomainMask)
.first!
// ยกเว้นไฟล์จากการสำรองข้อมูล iCloud
var resourceValues = URLResourceValues()
resourceValues.isExcludedFromBackup = true
var fileURL = documentsURL.appendingPathComponent("cached_data.json")
try fileURL.setResourceValues(resourceValues)
การซิงค์ iCloud ทำงานผ่าน NSUbiquitousContainer หากแอปใช้ iCloud Documents ในกรณีนี้ ไฟล์จาก Documents Directory จะถูกซิงค์โดยอัตโนมัติระหว่างอุปกรณ์ของผู้ใช้ สำหรับแอปที่ไม่มี iCloud การซิงค์จะจำกัดเฉพาะการสำรองข้อมูล
ความแตกต่างระหว่าง Documents และ Caches เป็นหนึ่งในความเข้าใจผิดที่พบบ่อยที่สุดในหมู่นักพัฒนา iOS มือใหม่ ความแตกต่างหลัก: ระบบสามารถลบไฟล์จาก Caches ได้ทุกเมื่อเพื่อเพิ่มพื้นที่ว่าง แต่จะไม่มีวันแตะต้อง Documents โดยไม่ได้รับความรู้จากผู้ใช้
| คุณลักษณะ | Documents Directory | Caches Directory |
|---|---|---|
| การสำรอง ข้อมูล iCloud | ใช่ (โดยค่าเริ่มต้น) | ไม่ |
| การลบ โดยระบบ | ไม่เคย | เมื่อพื้นที่ไม่เพียงพอ |
| iTunes File Sharing | ใช่ (เมื่อเปิดใช้แฟล็ก) | ไม่ |
| วัตถุประสงค์ | ข้อมูลผู้ใช้ | แคช, ข้อมูลชั่วคราว |
| การกู้คืน ข้อมูล | ต้องการการคืนค่า | สามารถดาวน์โหลดซ้ำได้ |
ตาม เอกสารสำหรับนักพัฒนา Apple (2024) การใช้ Documents Directory อย่างไม่เหมาะสมเป็นหนึ่งในสาเหตุทั่วไปของการปฏิเสธแอประหว่างการตรวจสอบ: หากแอปจัดเก็บข้อมูลที่สามารถกู้คืนได้มากกว่าสองสามเมกะไบต์ใน Documents Apple แนะนำให้ย้ายไปยัง Caches หรือใช้ NSURLIsExcludedFromBackupKey
กฎที่ใช้งานได้จริง: หากผู้ใช้จะเสียใจเมื่อสูญเสียไฟล์ — เก็บไว้ใน Documents หากไฟล์สามารถดาวน์โหลดซ้ำหรือสร้างใหม่ได้ — เก็บไว้ใน Caches
นักพัฒนา iOS ที่มีประสบการณ์ได้พัฒนากฎหลายข้อที่ช่วยหลีกเลี่ยงปัญหากับ Documents Directory ในทุกขั้นตอนของวงจรชีวิตแอป — ตั้งแต่การพัฒนาไปจนถึงการเผยแพร่ใน App Store
เป็นประจำ ตรวจสอบขนาดของ Documents Directory ผ่าน FileManager.enumerator(at:includingPropertiesForKeys:) หากขนาดเกิน 100 MB สำหรับข้อมูลที่ไม่ใช่ของผู้ใช้ — นั่นเป็นเหตุผลที่ต้องพิจารณาสถาปัตยกรรมการจัดเก็บใหม่
สำหรับไฟล์ใด ๆ ที่สามารถดาวน์โหลดซ้ำได้ ให้ตั้งค่า isExcludedFromBackup = true ซึ่งจะลดภาระบนพื้นที่จัดเก็บ iCloud ของผู้ใช้และลดความเสี่ยงของการปฏิเสธโดย App Review
เมื่อเปลี่ยนรูปแบบข้อมูลใน Documents ให้วางแผนการย้ายข้อมูล: อย่าลบไฟล์เก่าจนกว่าจะแน่ใจว่าไฟล์ใหม่ถูกสร้างขึ้นอย่างถูกต้อง ใช้ไดเรกทอรีย่อยเฉพาะเวอร์ชัน
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
)
การปฏิบัติตามแนวทางเหล่านี้ช่วยลดความเสี่ยงของการสูญเสียข้อมูลผู้ใช้ ลดขนาดการสำรองข้อมูล iCloud และทำให้การตรวจสอบ App Store ง่ายขึ้น
คำถามที่พบบ่อย
ได้ ผ่าน Files — แอปในตัวของ iOS ตั้งแต่เวอร์ชัน 11 เมื่อเปิดใช้คีย์ UIFileSharingEnabled ใน Info.plist เนื้อหาของ Documents Directory จะปรากฏในแอปไฟล์ในส่วน "บน iPhone ของฉัน" ผู้ใช้สามารถดู คัดลอก และลบไฟล์ได้
แซนด์บ็อกซ์ ทั้งหมดของแอป รวมถึง Documents Directory, Caches, tmp และ Library จะถูกลบออกจากอุปกรณ์อย่างสมบูรณ์ การสำรองข้อมูลใน iCloud จะถูกเก็บไว้จนกว่าจะกู้คืนหรือลบด้วยตนเอง เมื่อติดตั้งใหม่ แอปจะเริ่มต้นด้วยแซนด์บ็อกซ์ที่สะอาด
ใช้ FileManager.enumerator เพื่อสำรวจไฟล์ทั้งหมดในไดเรกทอรีและรวมขนาดของไฟล์เหล่านั้น สำหรับแต่ละไฟล์ ให้รับแอตทริบิวต์ .fileSize ผ่าน resourceValues(forKeys:) หรือใช้ URLResourceKey.fileSizeKey และ .directoryEnumerationResults
โดยค่าเริ่มต้น Core Data จะสร้างไฟล์ SQLite ใน Library/Application Support ไม่ใช่ใน Documents ไม่แนะนำให้ย้ายฐานข้อมูลไปยัง Documents — ฐานข้อมูลจะถูกรวมใน iTunes File Sharing และผู้ใช้สามารถลบหรือแก้ไขโดยไม่ตั้งใจได้ ข้อยกเว้นคือหากแอปให้ผู้ใช้เข้าถึงข้อมูลอย่างชัดเจนผ่าน Core Data
UIFileSharingEnabled (Application supports iTunes file sharing) คือคีย์บูลีนใน Info.plist เมื่อตั้งค่าเป็น YES ผู้ใช้สามารถคัดลอกไฟล์จาก Documents Directory ผ่าน iTunes และ Files เพิ่มคีย์ใน Info.plist: UIFileSharingEnabled = YES เปิดใช้เฉพาะเมื่อแอปสร้างเอกสารผู้ใช้จริง ๆ
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม