ITMS-91053: ret “Missing API declaration” i Expo
Af Mehdi Azizi
Udgivet , 8 min.
ITMS-91053: dit build bruger en required reason API uden at deklarere den. Tilføj kategori og kode i ios.privacyManifests, og lav et nyt build.
ITMS-91053 er et automatisk tjek fra Apple, som du får på mail efter du har sendt dit build ind. Det betyder, at koden i din app bruger en "required reason" API (indstillinger, fildatoer, tid siden opstart, diskplads eller tastaturer) uden at forklare hvorfor i sit privacy manifest. Med Expo retter du det i ios.privacyManifests: den kategori, Apple nævner, den kode der beskriver din faktiske brug, og så et nyt build.
I Solys, mit vækkeur med minispil, er de her begrundelser deklareret i appens konfiguration. Her får du den rigtige deklaration, kommandoen der viser, hvad dine afhængigheder bruger, og det tjek, du skal lave på den endelige fil før indsendelse.
Hvad betyder fejlen ITMS-91053?
Beskeden hedder "ITMS-91053: Missing API declaration". Den fortæller, at koden i en bestemt fil i dit build refererer til en eller flere API'er, der kræver en begrundelse. Derefter lister den de berørte kategorier, for eksempel NSPrivacyAccessedAPICategoryUserDefaults.
De her API'er beder ikke brugeren om tilladelse. Men de kan bruges til at genkende en enhed, det Apple kalder fingerprinting. Det er forbudt, også når brugeren accepterer sporing. Apple forklarer det på sin side om required reason API'er: hver app og hvert SDK skal deklarere, hvorfor de bruger dem.
Samme side fastlægger reglen: siden 1. maj 2024 accepterer App Store Connect ikke længere en app, der ikke beskriver den brug i sit manifest. Nogle udviklere har fået mailen som en ren advarsel på et build, der blev accepteret. Regn ikke med det: behandl den som en blokering, og ret fejlen før næste indsendelse.
Ligesom de andre ITMS-fejl er det ikke en afvisning fra en reviewer. Ingen har åbnet din app: Apple har analyseret binærfilen.
iOS privacy manifest: filen PrivacyInfo.xcprivacy
Privacy manifestet er en fil ved navn PrivacyInfo.xcprivacy, som ligger i roden af appens bundle. Ifølge Apples dokumentation om privacy manifests beskriver den indsamlede data, sporing og required reason API'er. De sidste kommer i arrayet NSPrivacyAccessedAPITypes: én post per kategori med type og en liste over begrundelser.
Fælden: et manifest dækker kun sit eget bundle. Apple skriver det direkte: hver eksekverbar fil eller dynamisk bibliotek, der bruger de her API'er, skal have et manifest i sit bundle. Din apps manifest dækker ikke et indlejret framework, og et SDK kan ikke læne sig op ad din apps manifest.
Forveksl det ikke med de tekster i Info.plist, som ITMS-90683 kræver. De vises for brugeren i en anmodning om tilladelse. Manifestet bliver kun læst af Apple.
De 5 API-kategorier og deres begrundelseskoder
Det fulde navn på en kategori starter med NSPrivacyAccessedAPICategory. Listen over API'er og begrundelser står på siden for nøglen NSPrivacyAccessedAPIType, læst 15. oktober 2026.
| Kategori | Typisk API | Almindelig begrundelse |
|---|---|---|
| UserDefaults | UserDefaults | CA92.1 |
| FileTimestamp | creationDate | C617.1 |
| SystemBootTime | systemUptime | 35F9.1 |
| DiskSpace | volumeAvailableCapacityKey | E174.1 |
| ActiveKeyboards | activeInputModes | 54BD.1 |
De koder, du oftest støder på:
- CA92.1: appen læser og skriver sine egne indstillinger, som andre apps ikke har adgang til.
- 1C8F.1: indstillinger, der deles med en widget eller en extension i samme App Group.
- C617.1: datoer eller størrelse på filer, der ligger i appens container.
- 3B52.1: filer, som brugeren har valgt, for eksempel i en dokumentvælger.
- 35F9.1: måle tiden mellem to hændelser i appen eller køre en timer.
- E174.1: tjekke ledig plads før der skrives filer, med en synlig effekt for brugeren.
- 85F4.1: vise diskpladsen for brugeren.
Deklarér den begrundelse, der passer til din faktiske brug, ikke den der ser bredest ud. Apple præciserer, at de her API'er og deres data kun må bruges til de deklarerede formål og aldrig til sporing. To koder er forbeholdt tredjeparts-SDK'er: C56D.1 og 0A2A.1. De hører ikke hjemme i din apps manifest.
Deklarér privacy manifestet i Expo
Med Expo skriver du ikke selv filen. Du beskriver den under expo.ios.privacyManifests i app.json eller app.config, og prebuild genererer PrivacyInfo.xcprivacy. Det er metoden fra Expos dokumentation om privacy manifests.
Her er det rigtige uddrag af Solys' konfiguration. Nøglen indeholder også sporing og indsamlede data, som er fjernet her:
{
"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 og 35F9.1 gentager det, som React Native og appens Expo-moduler deklarerer. 1C8F.1 kommer fra Solys selv: appen deler indstillinger med sin widget via en App Group.
En fælde, du skal kende: hvis din ios-mappe er genereret og ignoreret af git, når en PrivacyInfo.xcprivacy, som du har skrevet i hånden i den mappe, aldrig med i buildet. EAS kører prebuild igen og genererer mappen på ny. Jeg så det selv i et af mine projekter 9. september 2026: det håndskrevne manifest var væk efter et prebuild. Deklarationen skal ligge i konfigurationen.
Sidste punkt: manifestet er en del af binærfilen. En remote update ændrer det ikke. Du skal lave et nyt build og sende det ind igen.
Tredjeparts-SDK'er med deres eget manifest
De fleste nyere biblioteker har deres eget manifest med. De Expo-pakker, der bruger de her API'er, har en PrivacyInfo.xcprivacy i deres ios-mappe, ligesom React Native. Problemet ligger i, hvordan de er linket til din app.
Expos dokumentation advarer: Apple læser ikke altid manifesterne korrekt fra CocoaPods-afhængigheder, der er linket statisk, og det gælder Expo-pakkerne. Derfor kan du blive nødt til at kopiere deres begrundelser over i din apps konfiguration.
For at begrænse det arbejde samler indstillingen ios.privacyManifestAggregationEnabled i expo-build-properties manifesterne fra CocoaPods-afhængighederne i én fil. I den Podfile, Expo genererer i mine projekter (SDK 57), er den sammenlægning slået til, medmindre du slår den fra.
Sammenlægningen har en grænse: den ser kun de afhængigheder, der har et manifest. Et gammelt bibliotek uden manifest forbliver usynligt. Læs derfor stien til den fil, der nævnes i mailen: den fortæller, hvor du skal rette.
| Nævnt fil | Hvor du retter |
|---|---|
| Appens eksekverbare fil | ios.privacyManifests |
En .framework | Opdatér SDK'et |
En extension .appex | Extensionens manifest |
Tjek før indsendelse
Expo foreslår, at du venter på Apples mail efter en indsendelse. Det virker, men hver runde koster et build. Her er de fire tjek, jeg laver først.
1. List, hvad dine afhængigheder deklarerer. Fra projektets rod:
find node_modules -name PrivacyInfo.xcprivacy -not -path '*/example/*' \
-exec grep -ho "NSPrivacyAccessedAPICategory[A-Za-z]*" {} + | sort | uniq -c
På Solys fandt kommandoen 15. oktober 2026 13 manifester og fire kategorier: fildatoer, indstillinger, tid siden opstart og diskplads. Hver kategori på listen skal findes i appens endelige manifest eller i manifestet for det framework, der bruger den.
2. Søg i din egen native kode. Egne moduler, plugins, targets som en widget: den kode deklarerer intet SDK for dig.
grep -rlE "UserDefaults|systemUptime|mach_absolute_time|creationDate|modificationDate|volumeAvailableCapacity|activeInputModes" \
--include='*.swift' --include='*.m' --include='*.mm' modules plugins targets
Tilpas mapperne til dit projekt. På Solys er det den søgning, der afslører de indstillinger, der deles via App Group, og derfor koden 1C8F.1.
3. Læs det genererede manifest. Kør npx expo prebuild -p ios, og åbn så ios/<YourAppName>/PrivacyInfo.xcprivacy. Pas på: kommandoen kan slette og genskabe ios-mappen. Hvis du har lavet ændringer i hånden der, så arbejd på en kopi af projektet.
4. Tjek det endelige build. Det er det eneste bevis, der tæller. Download IPA'en fra buildets side på expo.dev, og kør så på din Mac:
unzip -q MyApp.ipa -d ipa
find ipa/Payload -name PrivacyInfo.xcprivacy
plutil -p ipa/Payload/*.app/PrivacyInfo.xcprivacy
Anden linje lister alle indlejrede manifester, appens og frameworkenes. Tredje linje viser appens manifest, som du sammenligner med listen fra trin 1.
Hvad manifestet skal fortælle sammen med din side
Manifestet står ikke alene. Hvis det deklarerer sporing eller indsamlede data, skal din App Store-side og din privatlivspolitik sige det samme. En uoverensstemmelse mellem de tre kan senere koste en afvisning fra et menneske under guideline 5.1.1. Hvad der skal stemme overens, gennemgår jeg i privatlivspolitik for en app.
Send dit build uden ubehagelige overraskelser
ITMS-fejl er hurtige at rette, når du ved, hvordan du læser dem. De afvisninger, der kommer bagefter, kræver mere overblik: fremgangsmåden står på siden app afvist af Apple, og de hyppigste årsager står i hvorfor Apple afviser en app.
Vil du tjekke dit projekt før indsendelse, samler Apple Review Kit min tjekliste og Claude Code-skills, der gennemgår dit projekt. Hvis din indsendelse sidder fast, og du vil have et menneskeligt blik på det, så book en time med mig: vi gennemgår dit projekt over video, på din skærm. Og forbereder du din første udgivelse, så tag din gratis diagnose: den sætter trinene i rækkefølge og sender dig min tjekliste mod afvisninger fra Apple.
Ofte stillede spørgsmål
Blokerer ITMS-91053 indsendelsen af mit build?
Apple skriver, at App Store Connect siden 1. maj 2024 ikke længere accepterer apps, der ikke beskriver deres brug af de her API'er. Alligevel har nogle udviklere fået mailen på et accepteret build, som en advarsel. Uanset hvad: ret manifestet før næste build.
Hvilken begrundelseskode skal jeg vælge til UserDefaults?
CA92.1, hvis appen kun læser og skriver sine egne indstillinger. Tilføj 1C8F.1, hvis den deler dem med en widget eller en extension via en App Group. C56D.1 er forbeholdt tredjeparts-SDK'er: put den ikke i din apps manifest.
Skal jeg kopiere hvert SDK's manifest over i app.json?
Ikke nødvendigvis. Hvis sammenlægningen af manifester er slået til, samles CocoaPods-afhængighedernes manifester, når pods installeres. Kopiér kun en kategori, hvis den mangler i det endelige manifest, med den begrundelse der beskriver den faktiske brug.
Skal min widget eller extension have sit eget manifest?
Ifølge Apple skal hvert bundle, der indeholder en eksekverbar fil, som bruger de her API'er, have sit eget manifest. En extension er en separat eksekverbar fil i sit eget bundle: appens manifest dækker den ikke.
Kan man rette ITMS-91053 uden at lave et nyt build?
Nej. Privacy manifestet er en del af binærfilen. Ret konfigurationen, lav et nyt build, og test det i TestFlight, før du sender det til review.