ITMS-91053: betulkan “Missing API declaration” dengan Expo
Oleh Mehdi Azizi
Diterbitkan pada , 8 min
ITMS-91053: build anda guna API required reason tanpa mengisytiharkannya. Tambah kategori dan kodnya dalam ios.privacyManifests, kemudian buat build baharu.
ITMS-91053 ialah semakan automatik Apple yang dihantar melalui e-mel selepas build anda dihantar. Maksudnya, kod app anda menggunakan API "required reason" (preferences, tarikh fail, masa sejak but, ruang cakera atau papan kekunci) tanpa menerangkan sebabnya dalam privacy manifest. Dengan Expo, pembetulannya dibuat dalam ios.privacyManifests: kategori yang disebut oleh Apple, kod yang menerangkan penggunaan sebenar anda, kemudian build baharu.
Dalam Solys, app jam loceng saya yang ada permainan mini, sebab-sebab ini diisytiharkan dalam konfigurasi app. Di bawah ialah pengisytiharan sebenarnya, arahan yang menyenaraikan apa yang digunakan oleh dependency anda, dan semakan yang perlu dibuat pada fail akhir sebelum dihantar.
Apakah maksud ralat ITMS-91053?
Mesej itu bertajuk "ITMS-91053: Missing API declaration". Ia menyatakan bahawa kod dalam satu fail tertentu dalam build anda merujuk kepada satu atau lebih API yang memerlukan sebab. Kemudian ia menyenaraikan kategori yang terlibat, contohnya NSPrivacyAccessedAPICategoryUserDefaults.
API ini tidak meminta sebarang kebenaran daripada pengguna. Tetapi ia boleh digunakan untuk mengenal pasti peranti, yang Apple panggil fingerprinting. Ini dilarang, walaupun pengguna bersetuju untuk dijejak. Apple menerangkannya di halaman tentang API required reason: setiap app dan setiap SDK mesti mengisytiharkan sebab ia menggunakannya.
Halaman yang sama menetapkan peraturannya: sejak 1 Mei 2024, App Store Connect tidak lagi menerima app yang tidak menerangkan penggunaan ini dalam manifestnya. Ada developer yang melaporkan e-mel ini sebagai amaran biasa sahaja, pada build yang diterima. Jangan bergantung pada itu: anggap ia sebagai sekatan dan betulkan sebelum penghantaran seterusnya.
Seperti ralat ITMS lain, ini bukan penolakan oleh reviewer. Tiada siapa yang membuka app anda: Apple menganalisis binari.
Privacy manifest iOS: fail PrivacyInfo.xcprivacy
Privacy manifest ialah fail bernama PrivacyInfo.xcprivacy yang diletakkan di akar bundle app. Menurut dokumentasi Apple tentang privacy manifest, ia menerangkan data yang dikumpul, penjejakan dan API required reason. API ini dimasukkan dalam tatasusunan NSPrivacyAccessedAPITypes: satu entri bagi setiap kategori, dengan jenisnya dan senarai sebabnya.
Perangkapnya: sesebuah manifest hanya meliputi bundle miliknya sendiri. Apple menulisnya dengan jelas: setiap executable atau dynamic library yang menggunakan API ini mesti ada manifest dalam bundle sendiri. Manifest app anda tidak meliputi framework yang dibenamkan, dan SDK tidak boleh bergantung pada manifest app anda.
Jangan keliru dengan ayat dalam Info.plist yang diperlukan oleh ITMS-90683. Ayat itu dipaparkan kepada pengguna dalam permintaan kebenaran. Manifest pula hanya dibaca oleh Apple.
5 kategori API dan kod sebabnya
Nama penuh sesuatu kategori bermula dengan NSPrivacyAccessedAPICategory. Senarai API dan sebab boleh didapati di halaman kunci NSPrivacyAccessedAPIType, dibaca pada 15 Oktober 2026.
| Kategori | API biasa | Sebab biasa |
|---|---|---|
| UserDefaults | UserDefaults | CA92.1 |
| FileTimestamp | creationDate | C617.1 |
| SystemBootTime | systemUptime | 35F9.1 |
| DiskSpace | volumeAvailableCapacityKey | E174.1 |
| ActiveKeyboards | activeInputModes | 54BD.1 |
Kod yang paling kerap anda akan jumpa:
- CA92.1: app membaca dan menulis preferences sendiri, yang tidak boleh diakses oleh app lain.
- 1C8F.1: preferences yang dikongsi dengan widget atau extension dalam App Group yang sama.
- C617.1: tarikh atau saiz fail yang disimpan dalam container app.
- 3B52.1: fail yang dipilih oleh pengguna, contohnya dalam pemilih dokumen.
- 35F9.1: mengukur masa yang berlalu antara dua peristiwa dalam app, atau menjalankan pemasa.
- E174.1: menyemak ruang kosong sebelum menulis fail, dengan kesan yang kelihatan kepada pengguna.
- 85F4.1: memaparkan ruang cakera kepada pengguna.
Isytiharkan sebab yang sepadan dengan penggunaan sebenar anda, bukan yang nampak paling luas. Apple menegaskan bahawa API ini dan datanya hanya digunakan untuk sebab yang diisytiharkan, dan tidak sekali-kali untuk penjejakan. Dua kod dikhaskan untuk SDK pihak ketiga: C56D.1 dan 0A2A.1. Ia tidak patut ada dalam manifest app anda.
Mengisytiharkan privacy manifest dalam Expo
Dengan Expo, anda tidak menulis fail itu sendiri. Anda menerangkannya di bawah expo.ios.privacyManifests, dalam app.json atau app.config, dan prebuild akan menjana PrivacyInfo.xcprivacy. Inilah kaedah dalam dokumentasi Expo tentang privacy manifest.
Ini petikan sebenar daripada konfigurasi Solys. Kunci ini juga mengandungi penjejakan dan data yang dikumpul, yang dibuang di sini:
{
"expo": {
"ios": {
"privacyManifests": {
"NSPrivacyAccessedAPITypes": [
{
"NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategoryUserDefaults",
"NSPrivacyAccessedAPITypeReasons": ["CA92.1", "1C8F.1"]
},
{
"NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategoryFileTimestamp",
"NSPrivacyAccessedAPITypeReasons": ["C617.1"]
},
{
"NSPrivacyAccessedAPIType": "NSPrivacyAccessedAPICategorySystemBootTime",
"NSPrivacyAccessedAPITypeReasons": ["35F9.1"]
}
]
}
}
}
}
CA92.1, C617.1 dan 35F9.1 mengulang apa yang diisytiharkan oleh React Native dan modul Expo dalam app. 1C8F.1 datang daripada Solys sendiri: app ini berkongsi tetapan dengan widgetnya melalui App Group.
Satu perangkap yang perlu anda tahu: jika folder ios anda dijana dan diabaikan oleh git, PrivacyInfo.xcprivacy yang ditulis secara manual dalam folder itu tidak akan sampai ke build. EAS menjalankan semula prebuild dan menjana semula folder itu. Saya sendiri mengalaminya dalam salah satu projek saya pada 9 September 2026: manifest yang ditulis secara manual hilang selepas prebuild. Pengisytiharan mesti berada dalam konfigurasi.
Perkara terakhir: manifest ialah sebahagian daripada binari. Kemas kini jarak jauh tidak mengubahnya. Anda perlu buat build baharu dan hantar semula.
SDK pihak ketiga yang membawa manifest sendiri
Kebanyakan library terkini menyediakan manifest sendiri. Pakej Expo yang menggunakan API ini ada PrivacyInfo.xcprivacy dalam folder ios masing-masing, begitu juga React Native. Masalahnya datang daripada cara ia dipautkan ke app anda.
Dokumentasi Expo memberi amaran: Apple tidak membaca dengan betul semua manifest daripada dependency CocoaPods yang dipautkan secara statik, dan pakej Expo adalah begitu. Jadi anda mungkin perlu menyalin semula sebab-sebabnya ke dalam konfigurasi app anda.
Untuk mengurangkan kerja ini, tetapan ios.privacyManifestAggregationEnabled dalam expo-build-properties menggabungkan manifest dependency CocoaPods ke dalam satu fail. Dalam Podfile yang dijana oleh Expo untuk projek saya (SDK 57), penggabungan ini aktif, kecuali jika anda mematikannya.
Penggabungan ini ada hadnya: ia hanya nampak dependency yang menyediakan manifest. Library lama yang tiada manifest kekal tidak kelihatan. Jadi baca laluan fail yang disebut dalam e-mel: ia memberitahu di mana perlu dibetulkan.
| Fail yang disebut | Di mana perlu dibetulkan |
|---|---|
| Executable app | ios.privacyManifests |
Sebuah .framework | Kemas kini SDK |
Extension .appex | Manifest extension |
Semak sebelum menghantar
Expo mencadangkan supaya anda menunggu e-mel Apple selepas menghantar. Cara itu berkesan, tetapi setiap pusingan memakan satu build. Ini empat semakan yang saya buat terlebih dahulu.
1. Senaraikan apa yang diisytiharkan oleh dependency anda. Dari akar projek:
find node_modules -name PrivacyInfo.xcprivacy -not -path '*/example/*' \
-exec grep -ho "NSPrivacyAccessedAPICategory[A-Za-z]*" {} + | sort | uniq -c
Untuk Solys, pada 15 Oktober 2026, arahan ini menemui 13 manifest dan empat kategori: tarikh fail, preferences, masa sejak but dan ruang cakera. Setiap kategori yang tersenarai mesti ada dalam manifest akhir app, atau dalam manifest framework yang menggunakannya.
2. Cari dalam kod native anda sendiri. Modul buatan sendiri, plugin, target seperti widget: kod ini tiada SDK yang akan mengisytiharkannya bagi pihak anda.
grep -rlE "UserDefaults|systemUptime|mach_absolute_time|creationDate|modificationDate|volumeAvailableCapacity|activeInputModes" \
--include='*.swift' --include='*.m' --include='*.mm' modules plugins targets
Sesuaikan folder dengan projek anda. Untuk Solys, carian inilah yang menunjukkan preferences yang dikongsi melalui App Group, maka kod 1C8F.1.
3. Baca manifest yang dijana. Jalankan npx expo prebuild -p ios, kemudian buka ios/<NamaAppAnda>/PrivacyInfo.xcprivacy. Awas: arahan ini boleh memadam kemudian mencipta semula folder ios. Jika anda telah membuat perubahan manual di situ, bekerja pada salinan projek.
4. Semak build akhir. Inilah satu-satunya bukti yang penting. Muat turun IPA dari halaman build di expo.dev, kemudian jalankan di Mac anda:
unzip -q MonApp.ipa -d ipa
find ipa/Payload -name PrivacyInfo.xcprivacy
plutil -p ipa/Payload/*.app/PrivacyInfo.xcprivacy
Baris kedua menyenaraikan semua manifest yang dibenamkan, manifest app dan manifest framework. Baris ketiga memaparkan manifest app, untuk dibandingkan dengan senarai daripada langkah 1.
Apa yang manifest perlu selaraskan dengan halaman app anda
Manifest tidak berdiri sendiri. Jika ia mengisytiharkan penjejakan atau data yang dikumpul, halaman App Store dan dasar privasi anda mesti menyatakan perkara yang sama. Percanggahan antara ketiga-tiganya boleh menyebabkan penolakan oleh manusia kemudian, di bawah guideline 5.1.1. Apa yang perlu diselaraskan diterangkan dalam dasar privasi aplikasi.
Hantar build anda tanpa kejutan
Ralat ITMS cepat dibetulkan apabila anda tahu cara membacanya. Penolakan yang datang selepas itu memerlukan lebih banyak pertimbangan: langkah-langkahnya ada di halaman aplikasi ditolak oleh Apple, dan sebab yang paling kerap ada dalam kenapa Apple menolak app.
Untuk menyemak fail anda sebelum dihantar, Apple Review Kit menghimpunkan senarai semak saya dan skill Claude Code yang menyemak projek anda. Jika penghantaran anda tersekat dan anda mahu pandangan manusia, tempah sejam dengan saya: kita semak projek anda melalui panggilan video, di skrin anda. Dan jika anda sedang menyediakan pelancaran pertama, buat diagnostik percuma anda: ia menyusun semula langkah-langkah mengikut urutan dan menghantar senarai semak anti-penolakan Apple saya.
Soalan lazim
Adakah ITMS-91053 menyekat penghantaran build saya?
Apple menulis bahawa sejak 1 Mei 2024, App Store Connect tidak lagi menerima app yang tidak menerangkan penggunaan API ini. Namun ada developer yang menerima e-mel ini pada build yang diterima, sebagai amaran. Dalam kedua-dua kes, betulkan manifest sebelum build seterusnya.
Kod sebab mana yang perlu dipilih untuk UserDefaults?
CA92.1 jika app hanya membaca dan menulis preferences sendiri. Tambah 1C8F.1 jika ia berkongsinya dengan widget atau extension melalui App Group. C56D.1 dikhaskan untuk SDK pihak ketiga: jangan masukkan dalam manifest app anda.
Perlukah saya menyalin manifest setiap SDK ke dalam app.json?
Tidak semestinya. Jika penggabungan manifest aktif, manifest dependency CocoaPods dihimpunkan semasa pemasangan pod. Salin semula sesuatu kategori hanya jika ia tiada dalam manifest akhir, dengan sebab yang menerangkan penggunaan sebenar.
Adakah widget atau extension saya memerlukan manifest sendiri?
Menurut Apple, setiap bundle yang mengandungi executable yang menggunakan API ini mesti ada manifest sendiri. Extension ialah executable berasingan, dalam bundle sendiri: manifest app tidak meliputinya.
Bolehkah ITMS-91053 dibetulkan tanpa membuat build baharu?
Tidak. Privacy manifest ialah sebahagian daripada binari. Betulkan konfigurasi, buat build baharu, kemudian uji dalam TestFlight sebelum menghantarnya untuk semakan.