ITMS-91053: popravak „Missing API declaration” u Expou
Autor: Mehdi Azizi
Objavljeno , 8 min
ITMS-91053: build koristi API s obaveznim razlogom bez deklaracije. Dodaj kategoriju i kod u ios.privacyManifests, pa napravi novi build.
ITMS-91053 je Appleova automatska provjera koja stiže e-mailom nakon isporuke tvog builda. Kaže da kod tvoje aplikacije koristi API „s obaveznim razlogom” (postavke, datumi datoteka, vrijeme od pokretanja sustava, prostor na disku ili tipkovnice), a da u manifestu privatnosti nije objašnjeno zašto. U Expou se to popravlja u ios.privacyManifests: kategorija koju Apple navodi, kod koji opisuje tvoju stvarnu upotrebu, pa novi build.
U Solysu, mojoj budilici s mini-igrama, ti su razlozi deklarirani u konfiguraciji aplikacije. Evo njegove stvarne deklaracije, naredbe koja izlista što koriste tvoje ovisnosti i provjere koju treba napraviti na konačnoj datoteci prije slanja.
Što znači greška ITMS-91053?
Poruka nosi naslov „ITMS-91053: Missing API declaration”. Kaže da kod određene datoteke u tvom buildu poziva jedan ili više API-ja koji traže razlog. Zatim navodi kategorije o kojima je riječ, npr. NSPrivacyAccessedAPICategoryUserDefaults.
Ti API-ji ne traže nikakvo dopuštenje od korisnika. Ali mogu poslužiti za prepoznavanje uređaja, što Apple zove fingerprinting. To je zabranjeno, čak i kad korisnik pristane na praćenje. Apple to objašnjava na stranici o API-jima s obaveznim razlogom: svaka aplikacija i svaki SDK mora deklarirati zašto ih koristi.
Ista stranica postavlja pravilo: od 1. svibnja 2024. App Store Connect više ne prihvaća aplikaciju koja te upotrebe ne opiše u svom manifestu. Neki developeri su prijavili da im je taj e-mail stigao kao obično upozorenje, uz prihvaćen build. Ne računaj na to: tretiraj ga kao blokadu i popravi prije sljedećeg slanja.
Kao i ostale ITMS greške, ovo nije odbijanje od reviewera. Nitko nije otvorio tvoju aplikaciju: Apple je analizirao binarnu datoteku.
iOS privacy manifest: datoteka PrivacyInfo.xcprivacy
Manifest privatnosti je datoteka PrivacyInfo.xcprivacy u korijenu bundlea aplikacije. Prema Appleovoj dokumentaciji o privacy manifestima, opisuje prikupljene podatke, praćenje i API-je s obaveznim razlogom. Ovi zadnji idu u polje NSPrivacyAccessedAPITypes: jedan unos po kategoriji, s tipom i popisom razloga.
Zamka: manifest pokriva samo vlastiti bundle. Apple to piše: svaka izvršna datoteka ili dinamička biblioteka koja koristi te API-je mora imati manifest u svom bundleu. Manifest tvoje aplikacije ne pokriva ugrađeni framework, a SDK se ne može osloniti na manifest tvoje aplikacije.
Nemoj ga brkati s rečenicama u Info.plistu koje traži ITMS-90683. One se prikazuju korisniku u zahtjevu za dopuštenje. Manifest čita samo Apple.
5 kategorija API-ja i njihovi kodovi razloga
Puni naziv kategorije počinje s NSPrivacyAccessedAPICategory. Popis API-ja i razloga nalazi se na stranici ključa NSPrivacyAccessedAPIType, pročitanoj 15. listopada 2026.
| Kategorija | Tipičan API | Čest razlog |
|---|---|---|
| UserDefaults | UserDefaults | CA92.1 |
| FileTimestamp | creationDate | C617.1 |
| SystemBootTime | systemUptime | 35F9.1 |
| DiskSpace | volumeAvailableCapacityKey | E174.1 |
| ActiveKeyboards | activeInputModes | 54BD.1 |
Kodovi na koje ćeš najčešće naići:
- CA92.1: aplikacija čita i piše vlastite postavke, nedostupne drugim aplikacijama.
- 1C8F.1: postavke dijeljene s widgetom ili ekstenzijom iz iste App Group.
- C617.1: datumi ili veličina datoteka spremljenih u kontejneru aplikacije.
- 3B52.1: datoteke koje je korisnik odabrao, npr. u biraču dokumenata.
- 35F9.1: mjerenje vremena između dva događaja u aplikaciji ili pokretanje timera.
- E174.1: provjera slobodnog prostora prije pisanja datoteka, s vidljivim učinkom za korisnika.
- 85F4.1: prikaz prostora na disku korisniku.
Deklariraj razlog koji odgovara tvojoj stvarnoj upotrebi, ne onaj koji se čini najširim. Apple navodi da se ti API-ji i njihovi podaci koriste samo za deklarirane razloge, nikad za praćenje. Dva koda su rezervirana za SDK-ove trećih strana: C56D.1 i 0A2A.1. Njima nije mjesto u manifestu tvoje aplikacije.
Deklariranje privacy manifesta u Expou
U Expou datoteku ne pišeš sam. Opišeš je pod expo.ios.privacyManifests, u app.json ili app.config, a prebuild generira PrivacyInfo.xcprivacy. To je metoda iz Expo dokumentacije o privacy manifestima.
Evo stvarnog isječka konfiguracije Solysa. Ključ sadrži i praćenje i prikupljene podatke, ovdje izbačene:
{
"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 i 35F9.1 preuzimaju ono što deklariraju React Native i Expo moduli aplikacije. 1C8F.1 dolazi od samog Solysa: aplikacija dijeli postavke sa svojim widgetom preko App Groupa.
Zamka koju treba znati: ako je tvoja mapa ios generirana i ignorirana u gitu, PrivacyInfo.xcprivacy ručno napisan u toj mapi nikad ne stiže u build. EAS ponovno pokreće prebuild i regenerira mapu. Uvjerio sam se u to na jednom svom projektu 9. rujna 2026.: ručno napisan manifest nestao je nakon prebuilda. Deklaracija mora živjeti u konfiguraciji.
Zadnja stvar: manifest je dio binarne datoteke. Udaljeno ažuriranje ga ne mijenja. Treba napraviti novi build i ponovno ga poslati.
SDK-ovi trećih strana sa svojim manifestom
Većina novijih biblioteka dolazi sa svojim manifestom. Expo paketi koji koriste te API-je imaju PrivacyInfo.xcprivacy u svojoj mapi ios, kao i React Native. Problem je u načinu na koji su povezani s tvojom aplikacijom.
Expo dokumentacija upozorava: Apple ne čita ispravno sve manifeste statički povezanih CocoaPods ovisnosti, a takvi su Expo paketi. Zato ćeš možda morati prepisati njihove razloge u konfiguraciju svoje aplikacije.
Da smanjiš taj posao, postavka ios.privacyManifestAggregationEnabled iz expo-build-properties spaja manifeste CocoaPods ovisnosti u jednu datoteku. U Podfileu koji Expo generira na mojim projektima (SDK 57) to spajanje je uključeno, osim ako ga ne isključiš.
Spajanje ima ograničenje: vidi samo ovisnosti koje imaju manifest. Stara biblioteka bez njega ostaje nevidljiva. Zato pročitaj putanju datoteke navedenu u e-mailu: ona ti kaže gdje popraviti.
| Navedena datoteka | Gdje popraviti |
|---|---|
| Izvršna datoteka aplikacije | ios.privacyManifests |
.framework | Ažuriraj SDK |
Ekstenzija .appex | Manifest ekstenzije |
Provjera prije slanja
Expo predlaže da nakon slanja pričekaš Appleov e-mail. To radi, ali svaki krug košta jedan build. Evo četiri provjere koje radim prije.
1. Izlistaj što deklariraju tvoje ovisnosti. Iz korijena projekta:
find node_modules -name PrivacyInfo.xcprivacy -not -path '*/example/*' \
-exec grep -ho "NSPrivacyAccessedAPICategory[A-Za-z]*" {} + | sort | uniq -c
Na Solysu, 15. listopada 2026., naredba pronalazi 13 manifesta i četiri kategorije: datume datoteka, postavke, vrijeme od pokretanja i prostor na disku. Svaka izlistana kategorija mora se naći u konačnom manifestu aplikacije ili u manifestu frameworka koji je koristi.
2. Pretraži vlastiti nativni kod. Vlastiti moduli, pluginovi, targeti poput widgeta: taj kod nijedan SDK neće deklarirati umjesto tebe.
grep -rlE "UserDefaults|systemUptime|mach_absolute_time|creationDate|modificationDate|volumeAvailableCapacity|activeInputModes" \
--include='*.swift' --include='*.m' --include='*.mm' modules plugins targets
Prilagodi mape svom projektu. Na Solysu upravo ova pretraga otkriva postavke dijeljene preko App Groupa, otud kod 1C8F.1.
3. Pročitaj generirani manifest. Pokreni npx expo prebuild -p ios, pa otvori ios/<NomDeTonApp>/PrivacyInfo.xcprivacy. Pazi: ova naredba može obrisati i ponovno stvoriti mapu ios. Ako si u njoj nešto mijenjao ručno, radi na kopiji projekta.
4. Provjeri konačni build. To je jedini dokaz koji vrijedi. Preuzmi IPA sa stranice builda na expo.dev, pa na Macu pokreni:
unzip -q MonApp.ipa -d ipa
find ipa/Payload -name PrivacyInfo.xcprivacy
plutil -p ipa/Payload/*.app/PrivacyInfo.xcprivacy
Drugi redak izlistava sve ugrađene manifeste, onaj aplikacije i one frameworka. Treći prikazuje manifest aplikacije, koji usporediš s popisom iz koraka 1.
Što manifest mora govoriti uz tvoju stranicu u App Storeu
Manifest ne živi sam. Ako deklarira praćenje ili prikupljene podatke, tvoja stranica u App Storeu i politika privatnosti moraju govoriti isto. Neslaganje među njima troje kasnije te može koštati ljudskog odbijanja po guidelineu 5.1.1. Što treba uskladiti detaljno je opisano u članku politika privatnosti aplikacije.
Pošalji build bez neugodnih iznenađenja
ITMS greške brzo se popravljaju kad ih znaš čitati. Odbijanja koja dolaze poslije traže više odmaka: postupak je na stranici aplikacija koju je Apple odbio, a najčešći razlozi u članku zašto Apple odbija aplikaciju.
Za provjeru prije slanja, Apple Review Kit sadrži moju checklistu i Claude Code skillove koji pregledavaju tvoj projekt. Ako ti slanje zapne i želiš ljudski pogled, rezerviraj sat vremena sa mnom: prolazimo tvoj projekt preko videopoziva, na tvom ekranu. A ako pripremaš prvo izdanje, napravi besplatnu dijagnostiku: posložit će korake po redu i poslati ti moju checklistu protiv Appleovih odbijanja.
Česta pitanja
Blokira li ITMS-91053 slanje mog builda?
Apple piše da od 1. svibnja 2024. App Store Connect više ne prihvaća aplikacije koje ne opisuju upotrebu tih API-ja. Ipak, neki developeri su dobili e-mail uz prihvaćen build, kao upozorenje. U oba slučaja popravi manifest prije sljedećeg builda.
Koji kod razloga odabrati za UserDefaults?
CA92.1 ako aplikacija čita i piše samo vlastite postavke. Dodaj 1C8F.1 ako ih dijeli s widgetom ili ekstenzijom preko App Groupa. C56D.1 je rezerviran za SDK-ove trećih strana: ne stavljaj ga u manifest svoje aplikacije.
Moram li manifest svakog SDK-a prepisati u app.json?
Ne nužno. Ako je spajanje manifesta uključeno, manifesti CocoaPods ovisnosti spajaju se pri instalaciji podova. Kategoriju prepiši samo ako nedostaje u konačnom manifestu, s razlogom koji opisuje stvarnu upotrebu.
Treba li mom widgetu ili ekstenziji vlastiti manifest?
Prema Appleu, svaki bundle s izvršnom datotekom koja koristi te API-je mora imati vlastiti manifest. Ekstenzija je zasebna izvršna datoteka u vlastitom bundleu: manifest aplikacije je ne pokriva.
Može li se ITMS-91053 popraviti bez novog builda?
Ne. Manifest privatnosti dio je binarne datoteke. Popravi konfiguraciju, napravi novi build, pa ga testiraj u TestFlightu prije slanja na reviziju.