Privacy Manifest (PrivacyInfo.xcprivacy) เป็นไฟล์ที่แอปพลิเคชันและ SDK ของบุคคลที่สามทั้งหมดต้องรวมไว้ในบิลด์ iOS ตั้งแต่ฤดูใบไม้ผลิปี 2024 Apple กำหนดให้ต้องประกาศเหตุผลในการใช้ API ที่ได้รับการป้องกัน (Required Reason API) และประเภทของข้อมูลที่รวบรวม ตาม เอกสารประกอบนักพัฒนา Apple ทุกไบนารี ภายในแอปพลิเคชัน — เป้าหมายหลัก, เฟรมเวิร์ก, การพึ่งพา Swift Package Manager — ต้องมี Privacy Manifest ของตนเอง
ประเด็นสำคัญ
Privacy Manifest คือไฟล์ PrivacyInfo.xcprivacy ในรูปแบบ property list (XML) ที่ประกาศว่าแอปพลิเคชันเก็บรวบรวมข้อมูลประเภทใดและなぜใช้ API บางอย่าง Apple แนะนำไฟล์ประกาศซึ่งเป็นส่วนหนึ่งของโครงการเพิ่มความโปร่งใสด้านความเป็นส่วนตัว คล้ายกับ Privacy Nutrition Label แต่ในระดับโค้ดและไบนารี
วัตถุประสงค์หลักของไฟล์ประกาศคือการบันทึกการใช้ API ที่เรียกว่า Required Reason API เหล่านี้คือหมวดหมู่ API ที่อาจใช้สำหรับ การลายนิ้วมือดิจิทัล ของอุปกรณ์ (fingerprinting) ดังนั้นแต่ละการใช้ต้องมาพร้อมกับการประกาศเหตุผลเฉพาะจากรายการที่ Apple อนุมัติ
ตั้งแต่วันที่ 1 พฤษภาคม 2024 Apple ปฏิเสธบิลด์ที่ไม่มี Privacy Manifest สิ่งนี้ใช้กับทั้งเป้าหมายหลักของแอปพลิเคชันและ SDK และการพึ่งพาที่ฝังอยู่ทั้งหมด ตาม WWDC 2023 ไฟล์ประกาศเป็นข้อบังคับสำหรับแอปพลิเคชันทั้งหมดที่เผยแพร่ผ่าน App Store
ไฟล์ประกาศต้องมีอยู่ในทุกไบนารี — ไม่เพียงแต่ในแอปพลิเคชันหลัก แต่ยังรวมถึงทุกเฟรมเวิร์กและไลบรารีแบบสแตติกด้วย หาก SDK ของบุคคลที่สามไม่ได้จัดเตรียมไฟล์ประกาศ นักพัฒนาต้องเพิ่มด้วยตนเองหรือติดต่อผู้ให้บริการ SDK เพื่อขออัปเดต
ก่อนมีไฟล์ประกาศ นักพัฒนาสามารถใช้ API ระบบที่กว้างขวาง (การเข้าถึงระบบไฟล์, วันที่/เวลา, บันทึกระบบ) โดยไม่มี คำอธิบายที่โปร่งใส เกี่ยวกับวัตถุประสงค์การใช้งาน สิ่งนี้สร้างความเสี่ยงในการรั่วไหลของข้อมูลผ่าน SDK ของบุคคลที่สามที่อาจรวบรวมข้อมูลโดยที่นักพัฒนาไม่ทราบ
ตาม Mysk Inc. (2023) SDK ยอดนิยมหลายตัวใช้ API สำหรับการลายนิ้วมืออุปกรณ์โดยไม่มีความจำเป็นชัดเจน — ตัวอย่างเช่น การอ่านเวลาใช้งานเพื่อกำหนดเขตเวลาหรือการสแกนไดเรกทอรีเพื่อรวบรวมเมตาดาตา Privacy Manifest บังคับให้ประกาศทุกการกระทำดังกล่าว
นอกเหนือจาก Required Reason API แล้ว ไฟล์ประกาศยังรวมถึงส่วน NSPrivacyTracking — ตัวบ่งชี้ว่าแอปใช้การติดตามหรือไม่ (ต้องมี ATT) และ NSPrivacyCollectedDataTypes — รายการประเภทข้อมูลที่รวบรวมในรูปแบบ Privacy Nutrition Label
Privacy Nutrition Label คือการแสดงผลสำหรับผู้ใช้บนหน้าแอปใน App Store ที่แสดงว่าแอปเก็บรวบรวมข้อมูลใด Privacy Manifest คือ ไฟล์ทางเทคนิค ภายในไบนารีที่ Apple ตรวจสอบโดยอัตโนมัติ หากข้อมูลในไฟล์ประกาศไม่ตรงกับป้ายกำกับใน App Store Connect Apple จะปฏิเสธบิลด์
ดังนั้น ไฟล์ประกาศคือแหล่งความจริงสำหรับระบบตรวจสอบของ Apple ป้ายกำกับความเป็นส่วนตัวจะถูกสร้างขึ้นโดยอัตโนมัติจากไฟล์นี้ แต่นักพัฒนาต้องทำให้ทั้งสองการแสดงผลเป็นปัจจุบัน การเปลี่ยนแปลงไฟล์ประกาศหลังเผยแพร่จำเป็นต้องส่งบิลด์ใหม่เพื่อตรวจสอบ
ไฟล์ PrivacyInfo.xcprivacy ใช้รูปแบบ property list โดยมีประเภทหลักเป็น Dictionary คีย์ระดับบนสุดที่สำคัญคือ: NSPrivacyTracking (Boolean), NSPrivacyTrackingDomains (Array), NSPrivacyCollectedDataTypes (Array), NSPrivacyAccessedAPITypes (Array)
คีย์ NSPrivacyTracking — ค่าบูลีนที่ระบุว่าแอปใช้การติดตามหรือไม่ (ต้องมี ATT) หากเป็น true ต้องระบุ NSUserTrackingUsageDescription ใน Info.plist ด้วย คีย์ NSPrivacyTrackingDomains — อาร์เรย์ของโดเมนที่ใช้การติดตาม
คีย์ NSPrivacyCollectedDataTypes — อาร์เรย์ของพจนานุกรม แต่ละอันอธิบายประเภทข้อมูลที่รวบรวม: หมวดหมู่ (NSPrivacyCollectedDataType), การเชื่อมโยง (NSPrivacyCollectedDataLinked), วัตถุประสงค์ (NSPrivacyCollectedDataTypePurposes) วัตถุประสงค์รวมถึง: การโฆษณาของบุคคลที่สาม, การวิเคราะห์, การพัฒนาผลิตภัณฑ์ และการปรับแต่งเนื้อหา
คีย์ NSPrivacyAccessedAPITypes — อาร์เรย์ของพจนานุกรมสำหรับแต่ละหมวดหมู่ Required Reason API: หมวดหมู่ (NSPrivacyAccessedAPITypeReasons) — เหตุผลเฉพาะจากรายการที่ Apple อนุมัติ และ NSPrivacyAccessedAPIType — ตัวระบุหมวดหมู่ API
<!-- PrivacyInfo.xcprivacy -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
</array>
</dict>
</plist>
ประเภทข้อมูลแบ่งออกเป็นหลายหมวดหมู่: ข้อมูลการติดต่อ (ชื่อ, อีเมล, โทรศัพท์), การเงิน (ข้อมูลการชำระเงิน), ตัวระบุ (IDFA, ID ผู้ใช้), ข้อมูลการใช้งาน (บันทึก, การคลิก), การวินิจฉัย (บันทึกการขัดข้อง) และ เนื้อหาผู้ใช้ (รูปภาพ, วิดีโอ, ไฟล์) แต่ละหมวดหมู่จะถูกทำเครื่องหมายเพิ่มเติมว่า "เชื่อมโยงกับผู้ใช้" หรือ "ไม่เชื่อมโยง"
เชื่อมโยงหมายถึงข้อมูลเชื่อมโยงกับบัญชีผู้ใช้ ไม่เชื่อมโยงหมายถึงข้อมูลถูกรวบรวมหรือไม่ระบุชื่อ การทำเครื่องหมายนี้มีผลต่อวิธีที่ Apple แสดงป้ายกำกับความเป็นส่วนตัว: ข้อมูลที่เชื่อมโยงจะทำเครื่องหมายเป็นสีเหลือง ไม่เชื่อมโยง — สีเขียว
Apple ระบุหมวดหมู่ API หลายหมวดหมู่ แต่ละการใช้ต้องมาพร้อมกับเหตุผลเฉพาะจากรายการที่อนุมัติ เหตุผลคือรหัสที่ไม่ซ้ำกัน ตัวอย่างเช่น C617.1 หรือ 35F9.1 ซึ่งจับคู่กับวัตถุประสงค์เฉพาะที่ Apple อนุญาต
หมวดหมู่ NSPrivacyAccessedAPICategoryFileTimestamp รวมถึง API สำหรับเข้าถึงการประทับเวลาไฟล์ (creationDate, modificationDate) เหตุผล: C617.1 (การซิงค์ไฟล์), 3B52.1 (การสำรองข้อมูล), 0A2A.1 (การป้องกันการฉ้อโกง)
หมวดหมู่ NSPrivacyAccessedAPICategoryDiskSpace รวมถึง API สำหรับตรวจสอบพื้นที่ว่างบนดิสก์ (NSFileManager. การตรวจสอบ (NSFileManager) เหตุผล: E174.1 (การจัดการแคช), 85F4.1 (การดาวน์โหลดเนื้อหา), B728.1 (การวินิจฉัย)
หมวดหมู่ NSPrivacyAccessedAPICategorySystemBootTime รวมถึง API สำหรับเข้าถึงเวลาบูตระบบ (uptime) มีเพียงเหตุผลเดียว: 35F9.1 (การวัดเวลาเซสชันสำหรับการวิเคราะห์) การใช้อื่นใดถือเป็นการลายนิ้วมือ
แต่ละหมวดหมู่มีเหตุผลที่อนุมัติ 1 ถึง 5 ข้อ นักพัฒนาต้องเลือกเหตุผลที่ตรงกับการใช้งาน API จริงมากที่สุด การให้เหตุผลที่ไม่ถูกต้องอาจนำไปสู่ การปฏิเสธบิลด์ หรือการระงับบัญชี
ตั้งแต่วันที่ 1 พฤษภาคม 2024 SDK ของบุคคลที่สามทั้งหมด — ทั้งแบบไบนารีและโอเพนซอร์ส — ต้องรวม Privacy Manifest ในแพ็คเกจของตน Apple ตรวจสอบไฟล์ประกาศสำหรับการพึ่งพาทั้งหมด และหาก SDK อย่างน้อยหนึ่งตัวไม่มีไฟล์ประกาศ บิลด์จะถูกปฏิเสธ
SDK หลัก (Firebase, Adjust, AppsFlyer, Facebook SDK) ได้อัปเดตแพ็คเกจของตนแล้ว หากโปรเจ็กต์ของคุณใช้ SDK ที่ไม่ค่อยรู้จัก ให้ตรวจสอบเวอร์ชันและหากจำเป็น อัปเดต หรือติดต่อนักพัฒนา วิธีแก้ไขชั่วคราวคือเพิ่มไฟล์ประกาศสำหรับ SDK ด้วยตนเองในโปรเจ็กต์ แต่ไม่แนะนำเนื่องจากความไม่สอดคล้องกันระหว่างการอัปเดต
คุณสามารถสร้าง PrivacyInfo.xcprivacy ผ่านเทมเพลตในตัวของ Xcode 15+ หรือด้วยตนเอง มาดูทั้งสองตัวเลือกกัน
Xcode 15 มีเทมเพลต Privacy Manifest: File → New → File → Resource → Privacy Manifest Xcode สร้างไฟล์ด้วยโครงสร้างพื้นฐานและเติม NSPrivacyTracking และอาร์เรย์ว่างสำหรับ API และข้อมูล หลังจากการสร้าง คุณต้องระบุเหตุผลด้วยตนเองสำหรับแต่ละ Required Reason API ที่ใช้
เทมเพลตจะเพิ่มไฟล์ไปยังเป้าหมายหลักโดยอัตโนมัติ หากโปรเจ็กต์มีหลายเป้าหมาย (Extensions, Watch app) คุณต้องเพิ่มไฟล์ประกาศในแต่ละเป้าหมาย Xcode จะไม่ตรวจสอบการมีอยู่ของไฟล์ประกาศในการพึ่งพาในเวลาคอมไพล์ — เฉพาะในขั้นตอนการเก็บถาวร
// AppDelegate: การตรวจสอบไฟล์ประกาศในขั้นตอนการพัฒนา
import Foundation
func validatePrivacyManifest() {
guard let path = Bundle.main.path(
forResource: "PrivacyInfo", ofType: "xcprivacy"
) else {
print("ไม่พบ PrivacyInfo.xcprivacy")
return
}
guard let dict = NSDictionary(contentsOfFile: path)
else { return }
print("Privacy manifest loaded: \(dict.count) keys")
}
คุณสามารถสร้าง PrivacyInfo.xcprivacy ด้วยตนเองเป็นไฟล์ XML property list ทั่วไป โดยสร้างไฟล์ชื่อ PrivacyInfo.xcprivacy เขียนส่วนหัว plist มาตรฐาน และเพิ่ม พจนานุกรมราก ด้วยคีย์ที่จำเป็น ตรวจสอบให้แน่ใจว่าไฟล์ถูกเพิ่มในเป้าหมาย (Target Membership)
วิธีแบบ manual มีประโยชน์เมื่อคุณต้องเพิ่มไฟล์ประกาศในไลบรารีแบบสแตติกหรือการพึ่งพา Package Manager โดยไม่ต้องใช้ส่วนติดต่อ Xcode หลังจากการคอมไพล์ ให้ตรวจสอบว่าไฟล์รวมอยู่ในไบนารีโดยใช้คำสั่ง nm หรือการเก็บถาวร
ก่อนส่งบิลด์ไปยัง App Store คุณต้องตรวจสอบว่า Privacy Manifest ถูกต้องและสมบูรณ์ Apple มีเครื่องมือตรวจสอบหลายอย่าง
เมื่อเก็บถาวรโปรเจ็กต์ (Product → Archive) Xcode จะดำเนินการตรวจสอบไฟล์ประกาศ หากพบข้อผิดพลาด — ไฟล์ประกาศหายไป, เหตุผลไม่ถูกต้อง, หมวดหมู่ว่างเปล่า — การเก็บถาวรจะล้มเหลวพร้อม ข้อผิดพลาด บันทึกข้อผิดพลาดจะแสดงใน Issue navigator โดยระบุ SDK ที่มีปัญหาและหมวดหมู่ API
การตรวจสอบเพิ่มเติมจะดำเนินการฝั่ง App Store Connect เมื่ออัปโหลดบิลด์ หากการตรวจสอบล้มเหลว บิลด์จะถูกปฏิเสธพร้อมอีเมลอัตโนมัติที่มีตัวระบุ API ที่มีปัญหาและการแก้ไขที่แนะนำ
เพื่อทำให้การตรวจสอบเป็นอัตโนมัติ ให้ใช้สคริปต์ที่วิเคราะห์ไบนารีเพื่อหาการใช้ Required Reason API Apple จัดเตรียมเครื่องมือ libtool และสคริปต์ตรวจสอบสัญลักษณ์ แต่ชุมชนได้พัฒนายูทิลิตี้ที่สะดวกกว่า
# ค้นหาการใช้งาน API FileTimestamp ในไบนารี
nm MyApp.app/MyApp | grep "NSFileCreationDate"
# ตรวจสอบการมีอยู่ของ PrivacyInfo.xcprivacy ในแอปพลิเคชัน
find MyApp.app -name "*.xcprivacy"
ข้อผิดพลาดที่พบบ่อยที่สุดคือการไม่มีไฟล์ประกาศใน SDK ใด SDK หนึ่ง แม้ว่าเป้าหมายหลักจะมีไฟล์ประกาศ Apple จะตรวจสอบแต่ละไบนารีแยกกัน ข้อผิดพลาดที่พบบ่อยอันดับสองคือรหัสเหตุผลไม่ถูกต้อง: การใช้เหตุผลสำหรับหมวดหมู่ API หนึ่งกับ API จากอีกหมวดหมู่หนึ่ง
ข้อผิดพลาดอันดับสามคือ การประกาศมากเกินไป ของ API ที่ไม่ได้ใช้งานจริง นักพัฒนาเพิ่มเหตุผลที่เป็นไปได้ทั้งหมด "เผื่อไว้" ซึ่งทำให้ผู้ตรวจสอบ Apple ระแวง เพิ่มเฉพาะหมวดหมู่ที่ใช้งานจริงเท่านั้น ใช้ตัววิเคราะห์แบบสแตติกของ Xcode เพื่อตรวจสอบ
คำถามที่พบบ่อย
ตั้งแต่วันที่ 1 พฤษภาคม 2024 Apple ปฏิเสธ บิลด์ใดๆ ที่ไม่มีไฟล์ประกาศ ข้อผิดพลาดเกิดขึ้นในขั้นตอนการอัปโหลดไปยัง App Store Connect แอปพลิเคชันเก่าไม่ถูกบล็อก แต่การอัปเดตต้องการการรวมไฟล์ประกาศที่บังคับ
ใช่ ไฟล์ประกาศเป็นข้อบังคับสำหรับทุกแพลตฟอร์มของ Apple: iOS, iPadOS, macOS, tvOS, watchOS และ visionOS ข้อกำหนด Required Reason API เหมือนกันทุกแพลตฟอร์ม แม้ว่าชุด API อาจแตกต่างกันเล็กน้อย
หาก SDK ไม่ได้จัดเตรียมไฟล์ประกาศ ให้สร้างไฟล์ PrivacyInfo.xcprivacy แยกต่างหากและเพิ่มในกลุ่ม SDK ในโปรเจ็กต์ ระบุเหตุผลสำหรับ API ที่ SDK นี้ใช้ตาม เอกสารประกอบ ของ SDK
ได้ ในระหว่างการตรวจสอบอัตโนมัติ Apple เปรียบเทียบ เหตุผลที่ประกาศกับการเรียก API จริง ความไม่ตรงกันนำไปสู่การปฏิเสธ ในระหว่างการตรวจสอบด้วยตนเอง ผู้ตรวจสอบอาจขอคำชี้แจง
ใช่ Apple ตรวจสอบไฟล์ประกาศสำหรับ ทุก การพึ่งพา รวมถึง SPM ผู้ให้บริการแพ็คเกจต้องรวม PrivacyInfo.xcprivacy ในที่เก็บของตน Xcode เตือนเกี่ยวกับไฟล์ประกาศที่ขาดหายไประหว่างการเก็บถาวร
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม