# ITMS-90683: แก้ Missing purpose string ใน Expo

> ITMS-90683 คือ Info.plist ขาดคีย์คำอธิบายการเข้าถึงข้อมูลสำคัญ แก้ได้โดยเพิ่มคีย์ที่ Apple ระบุไว้ใน ios.infoPlist ของ app.json แล้ว build ใหม่

หน้าต้นฉบับ: [ITMS-90683: แก้ Missing purpose string ใน Expo](https://devoria.fr/th/blog/itms-90683-missing-purpose-string-expo)
ผู้เขียน: [Mehdi Azizi](https://devoria.fr/th/mehdi-azizi)
เผยแพร่: 2026-10-09
แก้ไขเนื้อหาล่าสุด: 2026-10-09


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 เขียนไว้ในเอกสารเรื่อง[การเข้าถึงทรัพยากรที่ได้รับการป้องกัน](https://developer.apple.com/documentation/uikit/requesting-access-to-protected-resources) ว่า App Review จะปฏิเสธแอปที่โค้ดเข้าถึงทรัพยากรเหล่านี้โดยไม่มี purpose string

นี่ไม่ใช่การปฏิเสธจาก reviewer การตรวจนี้เป็นแบบอัตโนมัติและเกิดตอนส่ง build ก่อนเข้าคิวรีวิว เหมือนกับ [ITMS-91053](https://devoria.fr/th/blog/itms-91053-missing-api-declaration-expo) ที่เกี่ยวกับ 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](https://devoria.fr/th/blog/guideline-5-1-2-third-party-ai-att-data-sharing))

Apple อธิบายแต่ละคีย์ไว้ในเอกสาร เช่นของ [NSPhotoLibraryUsageDescription](https://developer.apple.com/documentation/bundleresources/information-property-list/nsphotolibraryusagedescription) ซึ่งจำเป็นทันทีที่แอปใช้ API ที่อ่านหรือเขียนคลังรูปภาพ

## แก้ ITMS-90683 ในแอป Expo

1. **จดชื่อคีย์ที่ระบุในอีเมลของ Apple** ข้อความจะบอกชื่อที่ถูกต้องไว้
2. **เพิ่มคีย์นั้นใน config ของคุณ** ใต้ `ios.infoPlist` ตามที่[เอกสารของ Expo เรื่องสิทธิ์การเข้าถึง](https://docs.expo.dev/guides/permissions/)บอกไว้:

```json
{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSPhotoLibraryUsageDescription": "Solys ไม่เข้าถึงรูปภาพของคุณ และจะไม่ขอสิทธิ์นี้เลย"
      }
    }
  }
}
```

3. **build ใหม่** Expo ระบุไว้ว่าการแก้ Info.plist ทำผ่านการอัปเดตระยะไกลไม่ได้ ต้องใช้ binary ใหม่
4. **ส่ง build** ไปให้ Apple อีกครั้ง แล้วเลือก build นั้นในเวอร์ชันของคุณ

มีกับดักอยู่อย่างหนึ่งถ้าแอปคุณมีหลายภาษา: ไฟล์ภาษามีไว้แปลคีย์ ไม่ได้ประกาศคีย์ คีย์ต้องมีอยู่ใน `ios.infoPlist` ก่อน (หรือใน config ของ plugin ที่เกี่ยวข้อง) ไม่อย่างนั้นแอปอาจแครชตั้งแต่ครั้งแรกที่เรียกใช้

## ควรเขียนประโยคอะไร ถ้าแอปไม่ได้ใช้ข้อมูลนั้น?

Apple ต้องการคำอธิบายที่ถูกต้อง มีประโยชน์ และชัดเจน ถ้าแอปใช้ข้อมูลนั้นจริง ให้บอกว่าใช้ทำอะไรในประโยคเดียว: "แอปใช้กล้องเพื่อสแกนบาร์โค้ดบนตั๋วของคุณ"

ถ้าคีย์นั้นมีอยู่เพราะไลบรารีเท่านั้น Apple ให้ทางแก้สองทาง: เขียนประโยคอธิบาย หรือเอาโค้ดที่เข้าถึงข้อมูลออก เมื่อโค้ดนั้นมาจากไลบรารี คุณเอาออกง่ายๆ ไม่ได้ สำหรับ Solys ผมเลยเขียนตามความจริง: "Solys ไม่เข้าถึงรูปภาพของคุณ และจะไม่ขอสิทธิ์นี้เลย" นี่เป็นทางเลือกแบบใช้งานได้จริง build ถัดมาผ่านตอนส่ง แต่ผมรับประกันไม่ได้ว่า Apple จะยอมรับประโยคนี้เสมอ

## ตรวจหาคีย์ที่ขาดก่อนส่ง

จากโฟลเดอร์รากของโปรเจกต์ คำสั่งนี้จะแสดงรายชื่อไฟล์ของไลบรารีที่โค้ด iOS อ้างถึง API ที่ถูกจับตามากที่สุด:

```bash
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 ปฏิเสธ](https://devoria.fr/th/expertise/app-rejected-by-apple) และเหตุผลที่พบบ่อยที่สุดอยู่ใน[ทำไม Apple ถึงปฏิเสธแอป](https://devoria.fr/th/blog/apple-app-rejection-reasons-real-cases)

ถ้าอยากตรวจความพร้อมก่อนส่ง [Apple Review Kit](https://devoria.fr/th/kits/review-apple) รวม checklist ของผมกับ skills ของ Claude Code ที่ช่วยอ่านตรวจโปรเจกต์ของคุณไว้ให้ ถ้าการส่งติดขัดและอยากได้คนช่วยดู [จองเวลาหนึ่งชั่วโมงกับผม](https://devoria.fr/th/coaching) เราจะไล่ดูโปรเจกต์ของคุณผ่านวิดีโอคอลบนหน้าจอของคุณเอง และถ้าคุณกำลังเตรียมปล่อยแอปแรก [ทำแบบประเมินฟรี](https://devoria.fr/th/diagnostic) ซึ่งจะเรียงขั้นตอนให้เป็นลำดับ และส่ง 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 ของคุณก่อน


## โปรเจกต์ของคุณ

[Apple Review Kit](https://devoria.fr/th/kits/review-apple): เช็กลิสต์รีวิว App Store ที่ผมใช้ การปฏิเสธจาก Apple ที่ผมแก้แล้ว บันทึกถึงผู้ตรวจ และสอง skills ของ Claude Code ที่ตรวจแอปคุณ 29 €

[iOS Kit](https://devoria.fr/th/kits/ios): สร้างแอป iPhone ด้วย Claude Code: Starter Code ของแอปผม skills ที่ตรวจงาน และคิต Apple Review, Screenshots และ ASO 129,99 €
