ITMS-91053: popravi »Missing API declaration« v Expo
Avtor: Mehdi Azizi
Objavljeno , 8 min
ITMS-91053: tvoj build uporablja API z obveznim razlogom, ne da bi ga prijavil. Dodaj kategorijo in kodo v ios.privacyManifests ter naredi nov build.
ITMS-91053 je Applovo samodejno preverjanje, ki ga dobiš po e-pošti po oddaji builda. Pove ti, da koda tvoje aplikacije uporablja API »z obveznim razlogom« (nastavitve, datumi datotek, čas od zagona, prostor na disku ali tipkovnice), ne da bi v manifestu zasebnosti pojasnila, zakaj. V Expu to popraviš v ios.privacyManifests: kategorija, ki jo navaja Apple, koda, ki opisuje tvojo dejansko uporabo, nato nov build.
V Solysu, mojem budilniku z mini igrami, so ti razlogi prijavljeni v konfiguraciji aplikacije. Tukaj je njegova dejanska prijava, ukaz, ki izpiše, kaj uporabljajo tvoje odvisnosti, in preverjanje končne datoteke pred oddajo.
Kaj pomeni napaka ITMS-91053?
Sporočilo ima naslov »ITMS-91053: Missing API declaration«. Pove, da koda v točno določeni datoteki tvojega builda kliče enega ali več API-jev, ki zahtevajo razlog. Nato našteje kategorije, na primer NSPrivacyAccessedAPICategoryUserDefaults.
Ti API-ji od uporabnika ne zahtevajo nobenega dovoljenja. Lahko pa služijo za prepoznavanje naprave, kar Apple imenuje fingerprinting. To je prepovedano, tudi če uporabnik sledenje sprejme. Apple to razloži na strani o API-jih z obveznim razlogom: vsaka aplikacija in vsak SDK mora prijaviti, zakaj jih uporablja.
Ista stran postavi pravilo: od 1. maja 2024 App Store Connect ne sprejme več aplikacije, ki teh uporab ne opiše v svojem manifestu. Nekateri razvijalci so ta e-mail dobili le kot opozorilo, pri sprejetem buildu. Ne zanašaj se na to: obravnavaj ga kot blokado in popravi pred naslednjo oddajo.
Kot pri drugih napakah ITMS to ni zavrnitev recenzenta. Nihče ni odprl tvoje aplikacije: Apple je analiziral binarno datoteko.
Privacy manifest za iOS: datoteka PrivacyInfo.xcprivacy
Manifest zasebnosti je datoteka z imenom PrivacyInfo.xcprivacy v korenu bundla aplikacije. Po Applovi dokumentaciji o privacy manifestih opisuje zbrane podatke, sledenje in API-je z obveznim razlogom. Ti gredo v tabelo NSPrivacyAccessedAPITypes: en vnos na kategorijo, z njenim tipom in seznamom razlogov.
Past: manifest pokriva samo svoj bundle. Apple to napiše: vsaka izvršljiva datoteka ali dinamična knjižnica, ki uporablja te API-je, mora imeti manifest v svojem bundlu. Manifest tvoje aplikacije ne pokriva vgrajenega frameworka, SDK pa se ne more zanašati na manifest tvoje aplikacije.
Ne zamenjaj ga s stavki v Info.plist, ki jih zahteva ITMS-90683. Ti se uporabniku prikažejo v prošnji za dovoljenje. Manifest pa bere samo Apple.
5 kategorij API-jev in njihove kode razlogov
Polno ime kategorije se začne z NSPrivacyAccessedAPICategory. Seznam API-jev in razlogov je na strani ključa NSPrivacyAccessedAPIType, prebrano 15. oktobra 2026.
| Kategorija | Tipičen API | Pogost razlog |
|---|---|---|
| UserDefaults | UserDefaults | CA92.1 |
| FileTimestamp | creationDate | C617.1 |
| SystemBootTime | systemUptime | 35F9.1 |
| DiskSpace | volumeAvailableCapacityKey | E174.1 |
| ActiveKeyboards | activeInputModes | 54BD.1 |
Kode, na katere boš naletel najpogosteje:
- CA92.1: aplikacija bere in piše svoje lastne nastavitve, ki drugim aplikacijam niso dostopne.
- 1C8F.1: nastavitve, deljene z widgetom ali razširitvijo v isti App Group.
- C617.1: datumi ali velikost datotek v vsebniku aplikacije.
- 3B52.1: datoteke, ki jih je izbral uporabnik, na primer v izbirniku dokumentov.
- 35F9.1: merjenje časa med dvema dogodkoma v aplikaciji ali poganjanje časovnika.
- E174.1: preverjanje prostega prostora pred pisanjem datotek, z učinkom, ki ga uporabnik vidi.
- 85F4.1: prikaz prostora na disku uporabniku.
Prijavi razlog, ki ustreza tvoji dejanski uporabi, ne tistega, ki se zdi najširši. Apple poudarja, da se ti API-ji in njihovi podatki uporabljajo samo za prijavljene razloge in nikoli za sledenje. Dve kodi sta rezervirani za SDK-je tretjih oseb: C56D.1 in 0A2A.1. V manifestu tvoje aplikacije jima ni mesta.
Prijava privacy manifesta v Expu
V Expu datoteke ne pišeš sam. Opišeš jo pod expo.ios.privacyManifests, v app.json ali app.config, prebuild pa ustvari PrivacyInfo.xcprivacy. To je metoda iz Expove dokumentacije o privacy manifestih.
Tu je dejanski izsek konfiguracije Solysa. Ključ vsebuje tudi sledenje in zbrane podatke, ki sem jih tu odstranil:
{
"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 in 35F9.1 povzemajo, kar prijavljajo React Native in Expo moduli aplikacije. 1C8F.1 prihaja iz samega Solysa: aplikacija si nastavitve deli s svojim widgetom prek App Groupa.
Past, ki jo moraš poznati: če je tvoja mapa ios generirana in jo git ignorira, ročno napisan PrivacyInfo.xcprivacy v tej mapi nikoli ne pride v build. EAS znova zažene prebuild in mapo ustvari na novo. To sem opazil na enem svojih projektov 9. septembra 2026: ročno napisan manifest je po prebuildu izginil. Prijava mora živeti v konfiguraciji.
Še zadnje: manifest je del binarne datoteke. Posodobitev na daljavo ga ne spremeni. Narediti moraš nov build in ga znova oddati.
SDK-ji tretjih oseb z lastnim manifestom
Večina novejših knjižnic ima svoj manifest. Expo paketi, ki uporabljajo te API-je, imajo PrivacyInfo.xcprivacy v svoji mapi ios, prav tako React Native. Težava je v tem, kako so povezani s tvojo aplikacijo.
Expova dokumentacija opozarja: Apple ne prebere pravilno vseh manifestov statično povezanih odvisnosti CocoaPods, kar velja za Expo pakete. Zato boš morda moral njihove razloge prepisati v konfiguracijo svoje aplikacije.
Da to delo zmanjšaš, nastavitev ios.privacyManifestAggregationEnabled v expo-build-properties združi manifeste odvisnosti CocoaPods v eno datoteko. V Podfilu, ki ga Expo ustvari na mojih projektih (SDK 57), je to združevanje vklopljeno, razen če ga izklopiš.
Združevanje ima omejitev: vidi samo odvisnosti, ki imajo manifest. Starejša knjižnica brez njega ostane nevidna. Zato preberi pot datoteke, navedeno v e-mailu: pove ti, kje popraviti.
| Navedena datoteka | Kje popraviti |
|---|---|
| Izvršljiva datoteka aplikacije | ios.privacyManifests |
.framework | Posodobi SDK |
Razširitev .appex | Manifest razširitve |
Preverjanje pred oddajo
Expo predlaga, da po oddaji počakaš na Applov e-mail. Deluje, a vsak krog stane en build. Tukaj so štiri preverjanja, ki jih naredim prej.
1. Izpiši, kaj prijavljajo tvoje odvisnosti. Iz korena projekta:
find node_modules -name PrivacyInfo.xcprivacy -not -path '*/example/*' \
-exec grep -ho "NSPrivacyAccessedAPICategory[A-Za-z]*" {} + | sort | uniq -c
Na Solysu je ukaz 15. oktobra 2026 našel 13 manifestov in štiri kategorije: datumi datotek, nastavitve, čas od zagona in prostor na disku. Vsaka izpisana kategorija mora biti v končnem manifestu aplikacije ali v manifestu frameworka, ki jo uporablja.
2. Preišči svojo nativno kodo. Lastni moduli, vtičniki, cilji, kot je widget: te kode noben SDK ne prijavi namesto tebe.
grep -rlE "UserDefaults|systemUptime|mach_absolute_time|creationDate|modificationDate|volumeAvailableCapacity|activeInputModes" \
--include='*.swift' --include='*.m' --include='*.mm' modules plugins targets
Mape prilagodi svojemu projektu. Na Solysu je prav to iskanje razkrilo nastavitve, deljene prek App Groupa, od tod koda 1C8F.1.
3. Preberi ustvarjeni manifest. Zaženi npx expo prebuild -p ios, nato odpri ios/<ImeTvojeAplikacije>/PrivacyInfo.xcprivacy. Pozor: ta ukaz lahko mapo ios izbriše in ustvari na novo. Če si v njej kaj spreminjal ročno, delaj na kopiji projekta.
4. Preveri končni build. To je edini dokaz, ki šteje. Prenesi IPA s strani builda na expo.dev, nato na Macu zaženi:
unzip -q MonApp.ipa -d ipa
find ipa/Payload -name PrivacyInfo.xcprivacy
plutil -p ipa/Payload/*.app/PrivacyInfo.xcprivacy
Druga vrstica izpiše vse vgrajene manifeste, aplikacijin in tiste iz frameworkov. Tretja prikaže manifest aplikacije, ki ga primerjaš s seznamom iz 1. koraka.
Kaj mora manifest povedati skupaj s tvojo stranjo v trgovini
Manifest ne živi sam. Če prijavlja sledenje ali zbrane podatke, morata tvoja stran v App Storu in tvoja politika zasebnosti povedati isto. Neskladje med vsemi tremi te lahko pozneje stane človeške zavrnitve po guideline 5.1.1. Kaj uskladiti, je podrobno opisano v članku politika zasebnosti za aplikacijo.
Oddaj build brez neprijetnih presenečenj
Napake ITMS se hitro popravijo, ko jih znaš brati. Zavrnitve, ki pridejo potem, zahtevajo več razmisleka: postopek je na strani aplikacija, ki jo je Apple zavrnil, najpogostejši razlogi pa v članku zakaj Apple zavrne aplikacijo.
Da preveriš svojo oddajo, Apple Review Kit združuje moj kontrolni seznam in skille za Claude Code, ki pregledajo tvoj projekt. Če se ti oddaja zatakne in želiš človeški pogled, rezerviraj uro z mano: projekt pregledava prek videoklica, na tvojem zaslonu. Če pa pripravljaš prvo izdajo, naredi brezplačno diagnostiko: korake postavi v pravi vrstni red in ti pošlje moj kontrolni seznam proti Applovim zavrnitvam.
Pogosta vprašanja
Ali ITMS-91053 blokira oddajo mojega builda?
Apple piše, da od 1. maja 2024 App Store Connect ne sprejema več aplikacij, ki ne opišejo uporabe teh API-jev. Nekateri razvijalci so e-mail kljub temu dobili pri sprejetem buildu, kot opozorilo. V obeh primerih popravi manifest pred naslednjim buildom.
Katero kodo razloga izbrati za UserDefaults?
CA92.1, če aplikacija bere in piše samo svoje nastavitve. Dodaj 1C8F.1, če jih deli z widgetom ali razširitvijo prek App Groupa. C56D.1 je rezervirana za SDK-je tretjih oseb: ne daj je v manifest svoje aplikacije.
Ali moram manifest vsakega SDK-ja prepisati v app.json?
Ne nujno. Če je združevanje manifestov vklopljeno, se manifesti odvisnosti CocoaPods združijo ob namestitvi podov. Kategorijo prepiši samo, če manjka v končnem manifestu, z razlogom, ki opisuje dejansko uporabo.
Ali moj widget ali razširitev potrebuje svoj manifest?
Po Applu mora imeti vsak bundle z izvršljivo datoteko, ki uporablja te API-je, svoj manifest. Razširitev je ločena izvršljiva datoteka v svojem bundlu: manifest aplikacije je ne pokriva.
Ali lahko ITMS-91053 popravim brez novega builda?
Ne. Manifest zasebnosti je del binarne datoteke. Popravi konfiguracijo, naredi nov build in ga preizkusi v TestFlightu, preden ga oddaš v pregled.