# ITMS-90338: kako popraviti “Non-public API usage” u Expou

> ITMS-90338: tvoj build sadrži metodu, funkciju ili klasu koju Apple smatra privatnom. Pronađi ovisnost koja je uzrok, ažuriraj je i napravi novi build.

Izvorna stranica: [ITMS-90338: kako popraviti “Non-public API usage” u Expou](https://devoria.fr/hr/blog/itms-90338-non-public-api-usage-expo)
Autor: [Mehdi Azizi](https://devoria.fr/hr/mehdi-azizi)
Objavljeno: 2026-11-04
Zadnja revizija sadržaja: 2026-11-04


ITMS-90338 je Appleova automatska provjera tvog builda. Javlja da se tvoj binarni fajl poziva na API-je koje Apple smatra privatnima: Objective-C metode, funkcije ili klase. **Rješenje: pronađi fajl naveden u e-mailu, prati trag do ovisnosti koja sadrži taj naziv, ažuriraj je ili preimenuj svoju metodu, pa napravi novi build.**

S Expoom naziv gotovo uvijek dolazi iz neke nativne biblioteke, rijetko iz tvog JavaScripta. 15. listopada 2026. pokrenuo sam naredbe za analizu iz ovog vodiča na simulatorskom buildu Solysa, moje budilice s mini-igrama (Expo SDK 57), i na iOS SDK-u iz Xcodea 26.2. Evo kako čitati e-mail, pronaći krivca i prepoznati lažnu uzbunu.

## Što znači greška ITMS-90338?

Poruka nosi naslov "ITMS-90338: Non-public API usage". Postoji u tri varijante, ovisno o tome što je Apple našao u tvom binarnom fajlu:

- **"references non-public selectors"**: nazivi Objective-C metoda, poput `boldFontOfSize:`;
- **"references non-public symbols"**: funkcije, napisane s donjom crtom ispred, poput `__dyld_get_shared_cache_range`;
- **"contains or inherits from non-public classes"**: naziv klase.

Svaka varijanta daje putanju, a zatim popis naziva. Tekst dodaje dva savjeta: preimenuj svoje metode ako im se naziv poklapa s privatnim API-jem i ukloni statičku biblioteku koja ih sadrži. E-mail iz rujna 2026. predlaže i `xcrun swift-demangle` da kodirani Swift nazivi postanu čitljivi.

Pravilo iza ove provjere je [guideline 2.5.1](https://developer.apple.com/app-store/review/guidelines/#2.5.1): aplikacija smije koristiti samo javne API-je. [Licencni ugovor Apple Developer Programa](https://developer.apple.com/support/terms/apple-developer-program-license-agreement/) to ponavlja u članku 3.3.1: nema pozivanja privatnih API-ja. Ljudska provjera tog pravila opisana je u vodiču za [guideline 2.5.1](https://devoria.fr/hr/blog/guideline-2-5-1-javni-api-sdk-expo). Ovdje se bavimo greškom pri slanju.

Kao i kod drugih ITMS grešaka, nitko nije otvorio tvoju aplikaciju: Apple je analizirao binarni fajl tijekom obrade builda. **Apple ne objavljuje nikakav popis privatnih API-ja: nazivi iz tvog e-maila jedini su pouzdan popis.**

## Čitanje putanje: SDK ili tvoj izvršni fajl?

Putanja napisana prije popisa govori ti u kojem fajlu tražiti.

- **`Frameworks/Nom.framework/Nom`**: naziv se nalazi u ugrađenom dinamičkom frameworku, dakle u određenom SDK-u. U buildu Solysa ta mapa sadrži 14 frameworka: Hermes, React Native, Expo module isporučene već kompajlirane i biblioteku za slike SDWebImage.
- **Samo naziv tvoje aplikacije**: naziv se nalazi u glavnom izvršnom fajlu. S Expoom on objedinjuje tvoj nativni kod i podove kompajlirane iz izvornog koda, po defaultu statički linkane. Tada uzrok može biti bilo koja nativna biblioteka.

## Stablo odluke: od navedenog naziva do rješenja

Idi redak po redak. Prvi koji odgovara tvom slučaju daje ti trag.

| Što vidiš                  | Gdje tražiti            | Rješenje                   |
| -------------------------- | ----------------------- | -------------------------- |
| Naziv s `$s` ili `_$s`     | `xcrun swift-demangle`  | Ponovno kroz stablo        |
| Nema ga u tvom IPA-u       | `grep` po bundleu       | Ponovno pošalji build      |
| Javni naziv na iOS-u       | Headeri iOS SDK-a       | Ponovno pošalji build      |
| `API_UNAVAILABLE(ios)`     | Headeri iOS SDK-a       | Ažuriraj paket             |
| U `Frameworks/X`           | SDK koji isporučuje X   | Ažuriraj SDK               |
| Selektor, tvoja aplikacija | Podovi i nativni moduli | Dodaj prefiks ili ažuriraj |
| Simbol `_nom`, tvoja app   | `nm -m`, zatim podovi   | Zamijeni poziv             |
| Klasa, tvoja aplikacija    | Tvoje klase i podovi    | Dodaj prefiks klasi        |

Retci "Ponovno pošalji build" označavaju lažnu uzbunu, o kojoj pišem niže.

## Korak 1: otvori poslani build

Radi na fajlu koji je stvarno poslan Appleu, ne na svom projektu. Preuzmi IPA sa stranice builda na expo.dev, pa na Macu pokreni:

```bash
unzip -q MonApp.ipa -d ipa
ls ipa/Payload/MonApp.app/Frameworks
otool -L ipa/Payload/MonApp.app/MonApp | grep PrivateFrameworks
```

Drugi redak ispisuje ugrađene frameworke. Treći traži izravnu vezu na neki Appleov privatni framework: ne smije ništa ispisati. Na Solysu `otool -L` ne nalazi nijedan privatni framework, ni u izvršnom fajlu ni u 14 frameworka.

## Korak 2: pronađi fajl koji sadrži naziv

Kreni široko. Traži navedeni naziv, bez donjih crta na početku, u cijelom bundleu:

```bash
grep -rl "dyld_get_shared_cache_range" ipa/Payload/MonApp.app
```

Naredba ispisuje fajlove koji sadrže taj tekst. Zatim suzi pretragu prema vrsti naziva (selektor, simbol, klasa), na pronađenom fajlu, označenom kao `Binaire`:

```bash
strings -a Binaire | grep -x "boldFontOfSize:"
nm -m Binaire | grep "_dyld_get_shared_cache_range"
nm -m Binaire | grep '_OBJC_CLASS_$_NomDeClasse'
```

**Za selektor koristi `strings`, ne `nm`.** Na React frameworku Solysa `nm` prikazuje metode s njihovom klasom, poput `-[RCTRootView initWithBridge:moduleName:initialProperties:]`, a nikad sam selektor `initWithBridge:`. `strings` ga pronalazi.

Za simbol pročitaj kraj retka. Na Solysu `nm -m` prikazuje npr. `(undefined) external __dyld_get_image_name (from libSystem)`: binarni fajl poziva funkciju, ali je ne sadrži, a isporučuje je libSystem. Ta je funkcija javna, kako pokazuje sljedeći korak.

## Korak 3: provjeri je li naziv stvarno privatan

Headeri iOS SDK-a opisuju javne API-je. Pretraga od nekoliko sekundi kaže nalazi li se navedeni naziv u njima i na kojim platformama. Kod simbola najprije ukloni donju crtu dodanu pri kompajliranju: `_SCDynamicStoreCreate` postaje `SCDynamicStoreCreate`.

```bash
SDK=$(xcrun --sdk iphoneos --show-sdk-path)
grep -rn "SCDynamicStoreCreate" "$SDK/usr/include" "$SDK"/System/Library/Frameworks/*/Headers
```

15. listopada 2026., s iOS SDK-om 26.2, ovo daju četiri naziva iz stvarnih ITMS-90338 e-mailova:

| Navedeni naziv                | U iOS SDK-u          | Tumačenje             |
| ----------------------------- | -------------------- | --------------------- |
| \_dyld_get_shared_cache_range | Nema ga              | Privatni API          |
| boldFontOfSize:               | Nema ga              | Privatno ili kolizija |
| SCDynamicStoreCreate          | API_UNAVAILABLE(ios) | Samo macOS            |
| isMainFrame                   | WebKit svojstvo      | Javno                 |

**Naziv koji postoji i dostupan je na iOS-u upućuje na lažnu uzbunu. Naziv kojeg nema upućuje na privatni API ili koliziju.** Dva ograničenja: API koji je javan samo u Swiftu ne pojavljuje se u tim headerima, a za accessor poput `setDelegate:` traži svojstvo `delegate`.

## Korak 4: prati trag do paketa

Ako putanja navodi framework, njegov naziv vodi do poda, a zatim do npm paketa:

```bash
grep -n "NomDuFramework" ios/Podfile.lock
npm explain nom-du-paquet
```

`npm explain` kaže koja ga je ovisnost instalirala, ako ga nikad nisi sam dodao.

Ako putanja navodi izvršni fajl, traži naziv u nativnom izvornom kodu, pa u podovima:

```bash
grep -rl --include='*.m' --include='*.mm' --include='*.swift' --include='*.h' \
  "boldFontOfSize" node_modules modules
grep -rl "boldFontOfSize" ios/Pods
```

Prilagodi popis mapa: `modules` je mapa lokalnih Expo modula. Mapa `ios/Pods` pojavljuje se nakon `npx expo prebuild -p ios`, koja na Macu instalira i podove. Pazi: ta naredba može ponovno stvoriti mapu `ios`. Ako si je ručno mijenjao, radi na kopiji.

**Pretraga u `ios/Pods` jednako je važna kao pretraga izvornog koda.** Na Solysu ta mapa sadrži 15 frameworka isporučenih već kompajliranih, u formatu `.xcframework`: Expo module, Hermes, React Native i SDK-ove trećih strana. Pretraga ograničena na izvorne fajlove promašila bi njihov kod.

## Tipični uzroci

**SDK treće strane, prestar ili prenov.** U rujnu 2026. jedan je Flutter developer [prijavio odbijanje zbog sigurnosnog SDK-a](https://github.com/talsec/Free-RASP-Flutter/issues/236): njegova verzija 8.2.3 pozivala je `__dyld_get_shared_cache_range`. Verzija 8.2.2 je prolazila, a izdavač je savjetovao povratak na nju dok ne stigne ispravak.

**Nativni modul koji poziva nedokumentirani API.** Tvoj vlastiti modul, plugin ili neka mala biblioteka može koristiti internu UIKit metodu pronađenu na nekom forumu. Provjera je prepoznaje po nazivu.

**Kolizija naziva.** Tvoja metoda ili klasa slučajno nosi naziv Appleovog privatnog API-ja. Poruka to predviđa i traži da je preimenuješ. Apple preporučuje [dodavanje prefiksa metodama koje dodaješ njegovim klasama](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html), npr. tri mala slova i donju crtu.

**API koji je javan na macOS-u, ali ne i na iOS-u.** 2024. godine jedna je .NET MAUI aplikacija [odbijena zbog `_SCDynamicStoreCreate`](https://github.com/dotnet/runtime/issues/103949). Apple tu funkciju jest dokumentirao, ali [samo za macOS](https://developer.apple.com/documentation/systemconfiguration/1437828-scdynamicstorecreate), a header iOS SDK-a označava je s `API_UNAVAILABLE(ios, tvos, watchos)`.

## Popravi, ne zaobilazi

1. **Ažuriraj ovisnost.** Za pakete koje prati Expo, `npx expo install --check` javlja one koji ne odgovaraju tvom SDK-u, prema [dokumentaciji Expo CLI-ja](https://docs.expo.dev/more/expo-cli/). Za ostale pročitaj changelog.
2. **Vrati se na prethodnu verziju** ako je nova uvela taj naziv, i obavijesti izdavača.
3. **Zamijeni ili ukloni** napuštenu biblioteku.
4. **Preimenuj** svoju metodu ili klasu, uz prefiks.

**Nemoj skrivati naziv.** Rezanje stringa ili pozivanje metode zaobilaznim putem skriva korištenje, ali ga ne ispravlja. I dalje je zabranjeno pravilom 2.5.1 i ugovorom, a tada je izložen tvoj račun.

Zatim napravi novi build s novim [brojem builda](https://devoria.fr/hr/blog/app-store-connect-build-number-verzija). Ažuriranje na daljinu nije dovoljno: naziv je u kompajliranom nativnom kodu. Prije slanja ponovno pokreni korak 2 na novom IPA-u. Naziv se više ne smije pojaviti.

## Kad je riječ o lažnoj uzbuni

Appleova provjera ponekad griješi. 6. lipnja 2022. React Native i Flutter aplikacije dobile su ITMS-90338 zbog javnih WebKit naziva, poput `setNavigationDelegate:` ili `isMainFrame`, čak i za gotovo nepromijenjena ažuriranja. Sutradan je jedan Appleov inženjer napisao da je problem riješen na strani validacije i pozvao na ponovno slanje buildova. Rasprava je sačuvana u [Expoovom GitHub repozitoriju](https://github.com/expo/expo/issues/17768).

Tri znaka zajedno upućuju na lažnu uzbunu:

- build je sličan zadnjem prihvaćenom buildu;
- korak 2 ne pronalazi naziv ili ga korak 3 pokazuje kao javan na iOS-u;
- drugi developeri istog dana prijavljuju istu grešku na Appleovim forumima.

U tom slučaju pogledaj [status Appleovih servisa](https://developer.apple.com/system-status/), pa ponovno pošalji build s novim brojem. Ako greška ostane, piši [Appleovoj podršci za developere](https://developer.apple.com/contact/) i priloži cijeli e-mail. Kolizija naziva, s druge strane, za Apple nije lažna uzbuna: preimenuj.

## Prije sljedećeg slanja

I ostale ITMS greške imaju svoj vodič: [ITMS-90725](https://devoria.fr/hr/blog/itms-90725-sdk-version-issue-expo) za verziju Xcodea, [ITMS-91053](https://devoria.fr/hr/blog/itms-91053-missing-api-declaration-expo) za privacy manifest i [ITMS-90034](https://devoria.fr/hr/blog/itms-90034-missing-invalid-signature-popravak) za potpis. Kad build bude prihvaćen, instaliraj ga preko [TestFlighta](https://devoria.fr/hr/blog/testflight-testiranje-iphone-aplikacije) prije reviewa.

Odbijanja od strane reviewera traže više odmaka: postupak je na stranici [aplikacija koju je Apple odbio](https://devoria.fr/hr/expertise/apple-odbio-aplikaciju), a najčešći razlozi su u članku [zašto Apple odbija aplikaciju](https://devoria.fr/hr/blog/apple-odbio-aplikaciju-razlozi).

Da provjeriš sve prije slanja, [Review Kit](https://devoria.fr/hr/kits/app-review) objedinjuje moju checklistu i Claude Code skillove koji pregledavaju tvoj projekt. Ako ti je slanje zapelo i želiš da netko pogleda, [rezerviraj sat vremena sa mnom](https://devoria.fr/hr/coaching): prolazimo kroz tvoj projekt preko videopoziva, na tvom ekranu. A ako pripremaš svoje prvo izdanje, [napravi besplatnu dijagnostiku](https://devoria.fr/hr/diagnostic): posložit će korake redom i poslati ti moju checklistu protiv Appleovih odbijanja.

## Česta pitanja

### Je li ITMS-90338 odbijanje od App Reviewa?

Nije. To je automatska provjera tijekom obrade builda, prije bilo kakvog ljudskog pregleda. Odbijeni build ne stiže ni u TestFlight ni na review. Privatni API koji kasnije uoči reviewer spada pod guideline 2.5.1.

### Može li se ITMS-90338 popraviti ažuriranjem na daljinu?

Ne može. Navedeni nazivi nalaze se u kompajliranom nativnom kodu binarnog fajla. Ažuriranje na daljinu mijenja samo JavaScript i resurse. Popravi ovisnost, napravi novi build i ponovno ga pošalji.

### Zašto Apple navodi metode koje nikad nisam napisao?

Zato što dolaze iz ugrađene biblioteke ili iz kolizije: neka ovisnost deklarira metodu koja nosi naziv privatnog API-ja. Apple čita nazive prisutne u binarnom fajlu, ne tvoj izvorni kod. Prati trag do paketa s `grep` i `npm explain`.

### Kako znati je li API javan na iOS-u?

Potraži njegov naziv u headerima iOS SDK-a, čiju putanju daje `xcrun --sdk iphoneos --show-sdk-path`, pa pročitaj njegovu dostupnost. To piše i na Appleovoj stranici dokumentacije. Funkcija dokumentirana samo za macOS nije javna na iPhoneu.

### Treba li nakon popravka promijeniti broj builda?

Treba. Pusti EAS da ga poveća: broj koji je već poslan za istu verziju može biti odbijen s greškom ITMS-90189.


## Tvoj projekt

[Review Kit](https://devoria.fr/hr/kits/app-review): Moja checklista za App Store pregled, moja Appleova odbijanja i kako sam ih ispravio, checklista za Google Play i tri Claude Code skilla. 49 €.

[iOS & Android Kit](https://devoria.fr/hr/kits/ios): Napravi svoju iPhone i Android aplikaciju s Claude Codeom: početni kod mojih aplikacija, put do trgovina i svi kitovi. 99 €.

[Dijagnoza: što te dijeli od tvoje iPhone aplikacije](https://devoria.fr/hr/diagnostic): 7 pitanja, 60 sekundi: saznaj što te stvarno koči da objaviš svoju iPhone aplikaciju, dobij svoj put u 4 koraka i kit koji ti odgovara.
