ITMS-90683: แก้ Missing purpose string ใน Expo
โดย Mehdi Azizi
เผยแพร่เมื่อ , 6 นาที
ITMS-90683 คือ Info.plist ขาดคีย์คำอธิบายการเข้าถึงข้อมูลสำคัญ แก้ได้โดยเพิ่มคีย์ที่ Apple ระบุไว้ใน ios.infoPlist ของ app.json แล้ว build ใหม่
ITMS-90683 คือการปฏิเสธอัตโนมัติจาก Apple ซึ่งจะส่งมาทางอีเมลไม่นานหลังจากคุณส่ง build ขึ้นไป ก่อนจะมีคนมารีวิวเสียอีก ความหมายคือในไฟล์ Info.plist ของคุณขาดประโยคที่อธิบายว่าทำไมแอปถึงเข้าถึงข้อมูลสำคัญ วิธีแก้มีแค่สองขั้นตอน: เพิ่มคีย์ที่ระบุในข้อความลงใน ios.infoPlist แล้ว build ใหม่
ผมเจอเองกับ Solys แอปนาฬิกาปลุกที่มีมินิเกม แถมเป็นข้อมูลที่แอปไม่ได้ใช้เลยด้วย ต่อไปนี้คือความหมายของข้อความนี้ สาเหตุที่มันเกิด และวิธีป้องกัน
ข้อผิดพลาด ITMS-90683 หมายถึงอะไร?
ข้อความเต็มมีหัวข้อว่า "ITMS-90683: Missing purpose string in Info.plist" ซึ่งบอกว่าโค้ดของแอปคุณอ้างถึง API ที่เกี่ยวกับข้อมูลสำคัญ (รูปภาพ กล้อง ไมโครโฟน ตำแหน่ง รายชื่อติดต่อ) แต่ใน Info.plist ไม่มีคีย์คำอธิบายที่ตรงกัน ข้อความจะระบุชื่อคีย์นั้นไว้ เช่น NSPhotoLibraryUsageDescription
ประโยคคำอธิบายนี้เรียกว่า "purpose string" เป็นข้อความที่ iOS แสดงในหน้าต่างขออนุญาต Apple เขียนไว้ในเอกสารเรื่องการเข้าถึงทรัพยากรที่ได้รับการป้องกัน ว่า App Review จะปฏิเสธแอปที่โค้ดเข้าถึงทรัพยากรเหล่านี้โดยไม่มี purpose string
นี่ไม่ใช่การปฏิเสธจาก reviewer การตรวจนี้เป็นแบบอัตโนมัติและเกิดตอนส่ง build ก่อนเข้าคิวรีวิว เหมือนกับ ITMS-91053 ที่เกี่ยวกับ privacy manifest build นั้นจะถูกตีกลับ และคุณต้องส่ง build ใหม่
ทำไม Apple ถึงปฏิเสธ ทั้งที่แอปคุณไม่ได้ใช้ข้อมูลนั้น
จุดนี้แหละที่ทำให้หลายคนงง Apple วิเคราะห์โค้ดที่อยู่ใน build ของคุณ ไม่ใช่สิ่งที่แอปทำจริง ถ้าไลบรารีที่คุณใส่มาในแอปมีการอ้างถึงคลังรูปภาพ ก็ต้องมีคีย์นี้ ถึงจะไม่มีหน้าจอไหนขอสิทธิ์เข้าถึงรูปภาพเลยก็ตาม ข้อความของ Apple เองก็บอกไว้ว่าไลบรารีหรือ SDK ภายนอก อาจอ้างถึง API เหล่านี้ได้ และยังต้องมี purpose string อยู่ดี
กรณีของผมเกิดเมื่อวันที่ 26 กันยายน 2026 ตอนจัดการ config ของ Solys ให้สะอาดขึ้น ผมลบคีย์ NSPhotoLibraryUsageDescription ออก เพราะแอปไม่ได้แตะรูปภาพเลย build ถัดมาโดนปฏิเสธด้วย ITMS-90683 สาเหตุคือไลบรารีของ Expo สองตัวที่แอปใช้ คือ expo-image และ expo-file-system มีโค้ดที่อ้างถึงคลังรูปภาพ build ก่อนหน้านั้นผ่าน เพราะตอนนั้นยังมีคีย์อยู่
บทเรียน: อย่าลบคีย์คำอธิบาย "เพราะเราไม่ได้ใช้" ให้ลบได้ก็ต่อเมื่อไม่มีไลบรารีไหนใน build อ้างถึง API นั้นแล้วเท่านั้น
คีย์ที่เจอบ่อยที่สุด
NSPhotoLibraryUsageDescription: อ่านหรือเขียนรูปภาพNSPhotoLibraryAddUsageDescription: เพิ่มรูปภาพ โดยไม่อ่านNSCameraUsageDescription: กล้องNSMicrophoneUsageDescription: ไมโครโฟนNSLocationWhenInUseUsageDescription: ตำแหน่งขณะใช้งานNSContactsUsageDescription: รายชื่อติดต่อNSUserTrackingUsageDescription: การติดตามเพื่อโฆษณา (App Tracking Transparency)
Apple อธิบายแต่ละคีย์ไว้ในเอกสาร เช่นของ NSPhotoLibraryUsageDescription ซึ่งจำเป็นทันทีที่แอปใช้ API ที่อ่านหรือเขียนคลังรูปภาพ
แก้ ITMS-90683 ในแอป Expo
- จดชื่อคีย์ที่ระบุในอีเมลของ Apple ข้อความจะบอกชื่อที่ถูกต้องไว้
- เพิ่มคีย์นั้นใน config ของคุณ ใต้
ios.infoPlistตามที่เอกสารของ Expo เรื่องสิทธิ์การเข้าถึงบอกไว้:
{
"expo": {
"ios": {
"infoPlist": {
"NSPhotoLibraryUsageDescription": "Solys ไม่เข้าถึงรูปภาพของคุณ และจะไม่ขอสิทธิ์นี้เลย"
}
}
}
}
- build ใหม่ Expo ระบุไว้ว่าการแก้ Info.plist ทำผ่านการอัปเดตระยะไกลไม่ได้ ต้องใช้ binary ใหม่
- ส่ง build ไปให้ Apple อีกครั้ง แล้วเลือก build นั้นในเวอร์ชันของคุณ
มีกับดักอยู่อย่างหนึ่งถ้าแอปคุณมีหลายภาษา: ไฟล์ภาษามีไว้แปลคีย์ ไม่ได้ประกาศคีย์ คีย์ต้องมีอยู่ใน ios.infoPlist ก่อน (หรือใน config ของ plugin ที่เกี่ยวข้อง) ไม่อย่างนั้นแอปอาจแครชตั้งแต่ครั้งแรกที่เรียกใช้
ควรเขียนประโยคอะไร ถ้าแอปไม่ได้ใช้ข้อมูลนั้น?
Apple ต้องการคำอธิบายที่ถูกต้อง มีประโยชน์ และชัดเจน ถ้าแอปใช้ข้อมูลนั้นจริง ให้บอกว่าใช้ทำอะไรในประโยคเดียว: "แอปใช้กล้องเพื่อสแกนบาร์โค้ดบนตั๋วของคุณ"
ถ้าคีย์นั้นมีอยู่เพราะไลบรารีเท่านั้น Apple ให้ทางแก้สองทาง: เขียนประโยคอธิบาย หรือเอาโค้ดที่เข้าถึงข้อมูลออก เมื่อโค้ดนั้นมาจากไลบรารี คุณเอาออกง่ายๆ ไม่ได้ สำหรับ Solys ผมเลยเขียนตามความจริง: "Solys ไม่เข้าถึงรูปภาพของคุณ และจะไม่ขอสิทธิ์นี้เลย" นี่เป็นทางเลือกแบบใช้งานได้จริง build ถัดมาผ่านตอนส่ง แต่ผมรับประกันไม่ได้ว่า Apple จะยอมรับประโยคนี้เสมอ
ตรวจหาคีย์ที่ขาดก่อนส่ง
จากโฟลเดอร์รากของโปรเจกต์ คำสั่งนี้จะแสดงรายชื่อไฟล์ของไลบรารีที่โค้ด iOS อ้างถึง API ที่ถูกจับตามากที่สุด:
grep -rlE "PHPhotoLibrary|AVCaptureDevice|CLLocationManager|CNContactStore|EKEventStore|ATTrackingManager" \
node_modules/*/ios node_modules/@*/*/ios
แต่ละชื่อตรงกับข้อมูลหนึ่งประเภท: PHPhotoLibrary คือรูปภาพ, AVCaptureDevice คือกล้องและไมโครโฟน, CLLocationManager คือตำแหน่ง, CNContactStore คือรายชื่อติดต่อ, EKEventStore คือปฏิทิน, ATTrackingManager คือการติดตาม สำหรับผลลัพธ์แต่ละรายการ ให้ตรวจว่ามีคีย์คำอธิบายที่ตรงกันอยู่ใน config ของคุณ
ตาข่ายนี้จับกรณีที่ผมเคยเจอได้ แต่ไม่ได้แทนการอ่านอีเมลของ Apple ซึ่งยังเป็นรายการเดียวที่เชื่อถือได้ เหมือนกับเรื่อง API ที่ไม่เป็นสาธารณะของ ITMS-90338 ตั้งแต่โดนปฏิเสธครั้งนั้น ผมตรวจแบบนี้ก่อนทุก build ใช้เวลาไม่กี่วินาที ขณะที่การโดน ITMS-90683 ทำให้เสีย build หนึ่งครั้งและเวลาที่ต้องทำใหม่
ส่ง build โดยไม่เจอเรื่องไม่คาดฝัน
ITMS-90683 แก้ได้เร็วถ้าอ่านเป็น เหมือนกับ ITMS-90725 ที่เกี่ยวกับเวอร์ชันของ Xcode ส่วนการปฏิเสธที่ตามมาจาก reviewer ต้องใช้มุมมองที่กว้างกว่านั้น ขั้นตอนอยู่ในหน้าแอปถูก Apple ปฏิเสธ และเหตุผลที่พบบ่อยที่สุดอยู่ในทำไม Apple ถึงปฏิเสธแอป
ถ้าอยากตรวจความพร้อมก่อนส่ง Apple Review Kit รวม checklist ของผมกับ skills ของ Claude Code ที่ช่วยอ่านตรวจโปรเจกต์ของคุณไว้ให้ ถ้าการส่งติดขัดและอยากได้คนช่วยดู จองเวลาหนึ่งชั่วโมงกับผม เราจะไล่ดูโปรเจกต์ของคุณผ่านวิดีโอคอลบนหน้าจอของคุณเอง และถ้าคุณกำลังเตรียมปล่อยแอปแรก ทำแบบประเมินฟรี ซึ่งจะเรียงขั้นตอนให้เป็นลำดับ และส่ง checklist กันโดน Apple ปฏิเสธของผมให้คุณ
คำถามที่พบบ่อย
ITMS-90683 เป็นการปฏิเสธจาก App Review หรือเปล่า?
ไม่ใช่ในแง่ของ reviewer ที่เป็นคน มันคือการตรวจอัตโนมัติกับ build ตอนส่ง ก่อนเข้าคิวรีวิว เหมือนกับ ITMS-90717 ที่เกี่ยวกับไอคอน ไม่มีใครเปิดแอปคุณเลย build ถูกตีกลับ คุณต้องแก้ Info.plist แล้วส่ง build ใหม่
ทำไม Apple ถึงขอคีย์สำหรับข้อมูลที่แอปผมไม่ได้ใช้?
เพราะ Apple วิเคราะห์โค้ดที่อยู่ใน build ไม่ใช่พฤติกรรมของแอป ถ้าไลบรารีที่ใส่มาอ้างถึงคลังรูปภาพหรือกล้อง ก็ต้องมีคีย์คำอธิบาย ถึงจะไม่มีหน้าจอไหนขอสิทธิ์นั้นเลยก็ตาม
แก้ ITMS-90683 ด้วยการอัปเดตระยะไกลได้ไหม?
ไม่ได้ คีย์ที่ขาดอยู่ใน Info.plist ซึ่งเป็นส่วนหนึ่งของ binary การอัปเดตระยะไกลแก้ไฟล์นี้ไม่ได้ คุณต้อง build ใหม่แล้วส่งให้ Apple อีกครั้ง
ต้องเพิ่ม NSPhotoLibraryUsageDescription ตรงไหนในโปรเจกต์ Expo?
ใน config ของแอป ใต้ ios.infoPlist พร้อมประโยคที่อธิบายการใช้งาน บางไลบรารียังมีการตั้งค่าเฉพาะใน plugin ของตัวเอง ซึ่งอาจเพิ่มคีย์อื่นด้วย เช่นโหมดทำงานเบื้องหลัง ไม่ว่าแบบไหน คีย์ต้องมีอยู่ใน config หลัก ไม่ใช่แค่ในไฟล์แปลภาษา
ควรลบคีย์คำอธิบายที่ไม่ได้ใช้ไหม?
ลบได้ก็ต่อเมื่อไม่มีไลบรารีไหนใน build อ้างถึง API นั้นแล้วเท่านั้น ไม่อย่างนั้นการส่งครั้งต่อไปจะโดนปฏิเสธด้วย ITMS-90683 ก่อนลบคีย์ ให้ค้นหาชื่อ API ในโค้ด iOS ของ dependencies ของคุณก่อน