# ITMS-90338: oprava „Non-public API usage“ v Expo

> ITMS-90338: tvůj build obsahuje metodu, funkci nebo třídu, kterou Apple považuje za privátní. Najdi viníka mezi závislostmi, aktualizuj ji a udělej nový build.

Původní stránka: [ITMS-90338: oprava „Non-public API usage“ v Expo](https://devoria.fr/cs/blog/itms-90338-non-public-api-usage-expo)
Autor: [Mehdi Azizi](https://devoria.fr/cs/mehdi-azizi)
Publikováno: 2026-11-04
Poslední revize obsahu: 2026-11-04


ITMS-90338 je automatická kontrola, kterou Apple provádí na tvém buildu. Říká, že tvůj binární soubor odkazuje na API, která Apple považuje za privátní: metody Objective-C, funkce nebo třídy. **Oprava: najdi soubor uvedený v e-mailu, dohledej závislost, která daný název obsahuje, aktualizuj ji nebo přejmenuj svou metodu a pak udělej nový build.**

U Expo pochází název skoro vždy z nativní knihovny, málokdy z tvého JavaScriptu. 15. října 2026 jsem příkazy z tohohle návodu spustil na simulátorovém buildu Solys, mého budíku s minihrami (Expo SDK 57), a na iOS SDK z Xcode 26.2. Ukážu ti, jak číst e-mail, najít viníka a poznat falešný poplach.

## Co znamená chyba ITMS-90338?

Zpráva má název „ITMS-90338: Non-public API usage“. Existuje ve třech variantách podle toho, co Apple v tvém binárním souboru našel:

- **„references non-public selectors“**: názvy metod Objective-C, třeba `boldFontOfSize:`;
- **„references non-public symbols“**: funkce, psané s podtržítkem na začátku, třeba `__dyld_get_shared_cache_range`;
- **„contains or inherits from non-public classes“**: název třídy.

Každá varianta uvádí cestu a pak seznam názvů. Text přidává dvě rady: přejmenovat tvé metody, pokud se jejich název shoduje s privátním API, a odstranit statickou knihovnu, která je obsahuje. E-mail ze září 2026 navíc nabízí `xcrun swift-demangle`, aby se zakódované názvy ze Swiftu daly přečíst.

Pravidlo za touhle kontrolou je [guideline 2.5.1](https://developer.apple.com/app-store/review/guidelines/#2.5.1): aplikace smí používat jen veřejná API. [Licenční smlouva Apple Developer Program](https://developer.apple.com/support/terms/apple-developer-program-license-agreement/) to opakuje v článku 3.3.1: žádné volání privátního API. Lidskou kontrolu tohoto pravidla podrobně rozebírá návod ke [guideline 2.5.1](https://devoria.fr/cs/blog/guideline-2-5-1-verejna-api-sdk-expo). Tady řešíme chybu při nahrávání.

Stejně jako u ostatních chyb ITMS tvou aplikaci nikdo neotevřel: Apple analyzoval binární soubor během zpracování buildu. **Apple žádný seznam privátních API nezveřejňuje: názvy z tvého e-mailu jsou jediný spolehlivý seznam.**

## Čtení cesty: SDK, nebo tvůj spustitelný soubor?

Cesta uvedená před seznamem ti řekne, ve kterém souboru hledat.

- **`Frameworks/Nom.framework/Nom`**: název je ve vloženém dynamickém frameworku, tedy v konkrétním SDK. V buildu Solys obsahuje tahle složka 14 frameworků: Hermes, React Native, moduly Expo dodávané už zkompilované a knihovnu na obrázky SDWebImage.
- **Jen název tvé aplikace**: název je v hlavním spustitelném souboru. U Expo ten spojuje tvůj nativní kód a pody zkompilované ze zdrojáků, ve výchozím stavu linkované staticky. Na vině tak může být jakákoli nativní knihovna.

## Strom: od uvedeného názvu k opravě

Projdi řádky popořadě. První, který odpovídá tvému případu, ti dá stopu.

| Co čteš                       | Kde hledat             | Oprava                     |
| ----------------------------- | ---------------------- | -------------------------- |
| Název s `$s` nebo `_$s`       | `xcrun swift-demangle` | Projít strom znovu         |
| V IPA se nedá najít           | `grep` na bundle       | Poslat build znovu         |
| Veřejný název na iOS          | Hlavičky iOS SDK       | Poslat build znovu         |
| `API_UNAVAILABLE(ios)`        | Hlavičky iOS SDK       | Aktualizovat balíček       |
| V `Frameworks/X`              | SDK, které dodává X    | Aktualizovat SDK           |
| Selektor, tvoje aplikace      | Pody a nativní moduly  | Přidat prefix/aktualizovat |
| Symbol `_nom`, tvoje aplikace | `nm -m`, pak pody      | Nahradit volání            |
| Třída, tvoje aplikace         | Tvoje třídy a pody     | Přidat prefix ke třídě     |

Řádky „Poslat build znovu“ označují falešný poplach, o kterém je řeč níž.

## Krok 1: otevři odeslaný build

Pracuj se souborem, který jsi Applu skutečně poslal, ne se svým projektem. Stáhni IPA ze stránky buildu na expo.dev a na Macu spusť:

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

Druhý řádek vypíše vložené frameworky. Třetí hledá přímý odkaz na privátní framework Applu: nesmí nic vypsat. U Solys `otool -L` nenajde žádný privátní framework, ani ve spustitelném souboru, ani ve 14 frameworcích.

## Krok 2: najdi soubor, který název obsahuje

Začni zeširoka. Hledej uvedený název, bez úvodních podtržítek, v celém bundlu:

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

Příkaz vypíše soubory, které tenhle text obsahují. Pak hledání zpřesni podle typu názvu (selektor, symbol, třída) na nalezeném souboru, označeném `Binaire`:

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

**Na selektor použij `strings`, ne `nm`.** Na frameworku React v Solys `nm` vypisuje metody i s jejich třídou, třeba `-[RCTRootView initWithBridge:moduleName:initialProperties:]`, nikdy samotný selektor `initWithBridge:`. `strings` ho najde.

U symbolu čti konec řádku. V Solys `nm -m` vypíše třeba `(undefined) external __dyld_get_image_name (from libSystem)`: binární soubor funkci volá, ale neobsahuje ji, dodává ji libSystem. Tahle konkrétní funkce je veřejná, jak ukáže další krok.

## Krok 3: ověř, jestli je název opravdu privátní

Hlavičky iOS SDK popisují veřejná API. Hledání na pár sekund ti řekne, jestli tam uvedený název je a na kterých platformách. U symbolu nejdřív odstraň podtržítko přidané při kompilaci: z `_SCDynamicStoreCreate` se stane `SCDynamicStoreCreate`.

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

15. října 2026 s iOS SDK 26.2 dopadly čtyři názvy ze skutečných e-mailů ITMS-90338 takhle:

| Uvedený název                 | V iOS SDK            | Výklad               |
| ----------------------------- | -------------------- | -------------------- |
| \_dyld_get_shared_cache_range | Chybí                | Privátní API         |
| boldFontOfSize:               | Chybí                | Privátní nebo kolize |
| SCDynamicStoreCreate          | API_UNAVAILABLE(ios) | Jen macOS            |
| isMainFrame                   | Vlastnost WebKitu    | Veřejné              |

**Název, který tam je a je dostupný na iOS, ukazuje na falešný poplach. Chybějící název ukazuje na privátní API nebo kolizi.** Dvě omezení: veřejné API dostupné jen ve Swiftu se v těchto hlavičkách neobjeví a u přístupové metody jako `setDelegate:` hledej vlastnost `delegate`.

## Krok 4: dohledej balíček

Pokud cesta uvádí framework, jeho název tě dovede k podu a pak k npm balíčku:

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

`npm explain` ti řekne, která závislost ho nainstalovala, pokud sis ho nikdy nepřidal sám.

Pokud cesta uvádí spustitelný soubor, hledej název v nativních zdrojácích a pak v podech:

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

Seznam složek si uprav: `modules` je složka lokálních modulů Expo. Složka `ios/Pods` se objeví po `npx expo prebuild -p ios`, který na Macu zároveň nainstaluje pody. Pozor: může znovu vytvořit složku `ios`. Pokud jsi ji ručně upravoval, pracuj na kopii.

**Hledání v `ios/Pods` je stejně důležité jako hledání ve zdrojácích.** V Solys obsahuje tahle složka 15 frameworků dodaných už zkompilovaných ve formátu `.xcframework`: moduly Expo, Hermes, React Native a SDK třetích stran. Hledání omezené na zdrojové soubory by jejich kód minulo.

## Typické příčiny

**SDK třetí strany, příliš staré nebo příliš nové.** V září 2026 jeden vývojář ve Flutteru [nahlásil zamítnutí kvůli bezpečnostnímu SDK](https://github.com/talsec/Free-RASP-Flutter/issues/236): jeho verze 8.2.3 volala `__dyld_get_shared_cache_range`. Verze 8.2.2 prošla a vydavatel doporučil vrátit se k ní, dokud nevyjde oprava.

**Nativní modul, který volá nedokumentované API.** Tvůj vlastní modul, plugin nebo malá knihovna může používat interní metodu UIKitu nalezenou na nějakém fóru. Kontrola ji pozná podle názvu.

**Kolize názvů.** Tvoje metoda nebo třída má náhodou stejný název jako privátní API Applu. Zpráva s tím počítá a žádá tě, abys ji přejmenoval. Apple doporučuje [přidávat prefix k metodám, které přidáváš do jeho tříd](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html), třeba tři malá písmena a podtržítko.

**API veřejné na macOS, ale ne na iOS.** V roce 2024 byla aplikace v .NET MAUI [zamítnuta kvůli `_SCDynamicStoreCreate`](https://github.com/dotnet/runtime/issues/103949). Apple tuhle funkci dokumentuje, ale [jen pro macOS](https://developer.apple.com/documentation/systemconfiguration/1437828-scdynamicstorecreate), a hlavička iOS SDK ji označuje jako `API_UNAVAILABLE(ios, tvos, watchos)`.

## Oprav to, neobcházej

1. **Aktualizuj závislost.** U balíčků, které Expo sleduje, ti `npx expo install --check` ukáže ty, které neodpovídají tvému SDK, podle [dokumentace Expo CLI](https://docs.expo.dev/more/expo-cli/). U ostatních si přečti changelog.
2. **Vrať se k předchozí verzi**, pokud název přinesla ta nová, a dej vědět vydavateli.
3. **Nahraď nebo odstraň** opuštěnou knihovnu.
4. **Přejmenuj** svou metodu nebo třídu a přidej prefix.

**Název neskrývej.** Rozdělení řetězce nebo volání metody oklikou použití jen schová, neopraví ho. Pořád to zakazuje pravidlo 2.5.1 i smlouva a v sázce je pak tvůj účet.

Pak udělej nový build s novým [číslem buildu](https://devoria.fr/cs/blog/app-store-connect-build-number-verze-cislo-buildu). Aktualizace na dálku nestačí: název je ve zkompilovaném nativním kódu. Před odesláním spusť krok 2 znovu na nové IPA. Název se už nesmí objevit.

## Když jde o falešný poplach

Kontrola Applu se občas splete. 6. června 2022 dostaly aplikace v React Native a Flutteru ITMS-90338 kvůli veřejným názvům z WebKitu, jako `setNavigationDelegate:` nebo `isMainFrame`, a to i u skoro nezměněných aktualizací. Další den napsal inženýr Applu, že problém je na straně validace vyřešený, a vyzval k opětovnému odeslání buildů. Vlákno je zachované v [GitHub repozitáři Expo](https://github.com/expo/expo/issues/17768).

Na falešný poplach ukazují tři indicie dohromady:

- build vypadá jako poslední přijatý build;
- krok 2 název nenajde nebo krok 3 ukáže, že je na iOS veřejný;
- ostatní vývojáři hlásí stejný den stejnou chybu na fórech Applu.

V tom případě se podívej na [stav služeb Applu](https://developer.apple.com/system-status/) a pošli build znovu s novým číslem. Pokud chyba přetrvává, napiš [vývojářské podpoře Applu](https://developer.apple.com/contact/) a přilož celý e-mail. Kolize názvů ale v očích Applu falešný poplach není: přejmenuj.

## Před dalším odesláním

Ostatní chyby ITMS mají taky svůj návod: [ITMS-90725](https://devoria.fr/cs/blog/itms-90725-sdk-version-issue-expo) pro verzi Xcode, [ITMS-91053](https://devoria.fr/cs/blog/itms-91053-missing-api-declaration-expo) pro privacy manifest a [ITMS-90034](https://devoria.fr/cs/blog/itms-90034-missing-or-invalid-signature-oprava) pro podpis. Jakmile je build přijatý, nainstaluj si ho přes [TestFlight](https://devoria.fr/cs/blog/testflight-testovani-iphone-aplikace) ještě před review.

Zamítnutí od revieweru chtějí víc nadhledu: postup najdeš na stránce [aplikace zamítnutá Applem](https://devoria.fr/cs/expertise/aplikace-zamitnuta-applem) a nejčastější důvody v článku [proč Apple zamítá aplikace](https://devoria.fr/cs/blog/apple-zamitl-aplikaci-duvody).

Pokud si chceš svůj projekt před odesláním zkontrolovat, [Review Kit](https://devoria.fr/cs/kits/app-review) obsahuje můj checklist a skills pro Claude Code, které tvůj projekt projdou. Pokud se ti odesílání zaseklo a chceš, aby se na to podíval člověk, [zarezervuj si se mnou hodinu](https://devoria.fr/cs/coaching): projdeme tvůj projekt přes videohovor, na tvé obrazovce. A pokud chystáš své první vydání, [udělej si bezplatnou diagnostiku](https://devoria.fr/cs/diagnostic): seřadí ti kroky a pošle ti můj checklist proti zamítnutí od Applu.

## Časté dotazy

### Je ITMS-90338 zamítnutí od App Review?

Ne. Je to automatická kontrola během zpracování buildu, ještě před jakoukoli lidskou kontrolou. Odmítnutý build se nedostane ani do TestFlightu, ani do review. Privátní API, které později najde reviewer, spadá pod guideline 2.5.1.

### Dá se ITMS-90338 opravit aktualizací na dálku?

Ne. Uvedené názvy jsou ve zkompilovaném nativním kódu binárního souboru. Aktualizace na dálku mění jen JavaScript a zdroje. Oprav závislost, udělej nový build a pošli ho znovu.

### Proč Apple uvádí metody, které jsem nikdy nenapsal?

Protože pocházejí z vložené knihovny nebo z kolize: nějaká závislost deklaruje metodu se stejným názvem jako privátní API. Apple čte názvy v binárním souboru, ne tvůj zdrojový kód. Dohledej balíček pomocí `grep` a `npm explain`.

### Jak poznám, jestli je API na iOS veřejné?

Hledej jeho název v hlavičkách iOS SDK, jejichž cestu vrátí `xcrun --sdk iphoneos --show-sdk-path`, a přečti si jeho dostupnost. Uvádí ji i stránka v dokumentaci Applu. Funkce zdokumentovaná jen pro macOS na iPhonu veřejná není.

### Musím po opravě změnit číslo buildu?

Ano. Nech ho EAS zvýšit: číslo, které už bylo pro stejnou verzi odeslané, může skončit odmítnutím ITMS-90189.


## Tvůj projekt

[Review Kit](https://devoria.fr/cs/kits/app-review): Můj checklist pro review v App Store, moje opravená zamítnutí od Applu, checklist pro Google Play a tři skilly pro Claude Code. 1 199 Kč.

[iOS & Android Kit](https://devoria.fr/cs/kits/ios): Vytvoř si aplikaci pro iPhone a Android s Claude Code: startovní kód mých aplikací, cesta až do obchodů a všechny kity. 2 399 Kč.

[Diagnostika: co tě dělí od tvé iPhone aplikace](https://devoria.fr/cs/diagnostic): 7 otázek, 60 sekund: zjistíš, co ti doopravdy brání vydat iPhone aplikaci, dostaneš cestu ve 4 krocích a kit přesně pro tebe.
