Unijny monit śledzenia w iOS 27.2: co wdrożyć
Od iOS 27.2 i iPadOS 27.2 aplikacja w Unii Europejskiej może pokazać alternatywny monit App Tracking Transparency, a aplikacja dystrybuowana we Francji, w Niemczech, we Włoszech, w Polsce lub w Rumunii dostaje wyłącznie tę wersję, zarówno z nowego wywołania, jak i ze starego. SDK bety 27.2 dodaje jedną metodę, requestTrackingAuthorization(usingExpandedInterface:additionalInformationAction:completionHandler:) (11 października: uwagi Apple do wydania iOS 27.2 beta 3 dwukrotnie zmieniają jej nazwę, najpierw na requestTrackingAuthorization(preferExpandedInterface:...), a potem na requestTrackingAuthorizationPreferringExpandedInterface, nazwę, która zostaje; 26 października: to selektor Objective-C, a strona dokumentacji Apple podaje metodę w Swifcie jako requestTrackingAuthorization(preferExpandedInterface:additionalInformationAction:completionHandler:)7), dostępną w iOS 27.2 i niedostępną na macOS, tvOS, watchOS oraz visionOS, a także jeden opcjonalny klucz Info.plist, NSUserTrackingMarkdownUsageDescription. Poza UE nowe wywołanie zachowuje się jak stare, reguła mówiąca, kiedy trzeba zapytać, nie zmienia się, a użytkowników z UE można zapytać ponownie rok po ich poprzedniej odpowiedzi. Kroki wdrożenia znajdują się niżej. Na symulatorze bety 27.2, z regionem ustawionym na Stany Zjednoczone, Niemcy, Holandię lub Francję, każde wywołanie, które udało mi się powtórzyć po czystym starcie, pokazało standardowy alert, czyli dokładnie to, co Apple dokumentuje jako zachowanie zapasowe dla urządzenia spoza UE; na podstawie tych dowodów arkusz pozostaje testem na urządzeniu.123456
Aktualizacja, 26 października: iOS 27.2 ukazał się dziś jako kompilacja 24B119, więc arkusz jest już na telefonach w pięciu krajach, a strona dokumentacji Apple ustaliła nazwę metody w Swifcie:
requestTrackingAuthorization(preferExpandedInterface:additionalInformationAction:completionHandler:), z wariantemasync, który zwraca status, wymienioną dla iOS 27.2, iPadOS 27.2 i Mac Catalyst 27.2 bez oznaczenia bety; strona nazwy z pierwszej bety, tej z fragmentu kodu i z listy kroków poniżej, zwraca 404. Informacje o wydaniu zachowują funkcję pod tym samym numerem radaru i wymieniają obie zmiany nazwy jako poprawione, przy czym drugą zapisano teraz po obu stronach w Objective-C, więc selektor zaczyna się odrequestTrackingAuthorizationPreferringExpandedInterface:, a metoda w Swifcie zachowujepreferExpandedInterface:jako pierwszą etykietę. Żaden nagłówek na tym Macu nie deklaruje nowej nazwy; Xcode 27.2 RC, którego SDK powinno ją deklarować, nie jest tu zainstalowane, więc fragment kodu nadal używa nazwy z pierwszej bety i nie został skompilowany z SDK 27.2 RC; przed wdrożeniem należy zmienić etykietę, a także selektor Objective-C, jeśli metoda jest wywoływana z tego języka. Wpis o informacjach o wydaniu iOS 27.2 zawiera pełną stronę wydania.7
TL;DR
- Komunikat Apple z 16 września. „Beginning with iOS 27.2 and iPadOS 27.2, developers will have the option to use an alternative version of the App Tracking Transparency system prompt in the EU. The requirements for when you must seek permission to track users will remain the same. Due to legal requirements, only the alternative version of the system prompt is available for apps distributed in Germany, France, Italy, Poland, and Romania.” (od iOS 27.2 i iPadOS 27.2 można w UE użyć alternatywnej wersji systemowego monitu App Tracking Transparency; wymagania dotyczące tego, kiedy trzeba prosić o zgodę, pozostają bez zmian, a z uwagi na wymogi prawne tylko ta alternatywna wersja jest dostępna dla aplikacji dystrybuowanych w Niemczech, we Francji, we Włoszech, w Polsce i w Rumunii).1
- Jedna nowa metoda. Plik
ATTrackingManager.hz SDK bety 27.2 deklarujerequestTrackingAuthorizationUsingExpandedInterface:additionalInformationAction:completionHandler:zAPI_AVAILABLE(ios(27.2)) API_UNAVAILABLE(macos, tvos, watchos, visionos). Komentarz w nagłówku: „This method behaves identically torequestTrackingAuthorizationWithCompletionHandler:in non-EU countries.” (poza UE metoda działa identycznie jak stara).3 (11 października: to nazwa metody z pierwszej bety; uwagi Apple do wydania iOS 27.2 beta 3 dwukrotnie zmieniają jej nazwę, najpierw narequestTrackingAuthorization(preferExpandedInterface:...), a potem narequestTrackingAuthorizationPreferringExpandedInterface, nazwę, która zostaje; 26 października: to selektor Objective-C, a strona dokumentacji Apple podaje metodę w Swifcie jakorequestTrackingAuthorization(preferExpandedInterface:additionalInformationAction:completionHandler:)7.)6 - Stare wywołanie również pokazuje arkusz w pięciu krajach. Strona dokumentacji Apple dla
requestTrackingAuthorization(completionHandler:): „In France, Germany, Italy, Poland, and Romania, the system presents a full-page sheet; otherwise, the system prompts the person with an alert.” (w tych pięciu krajach system pokazuje pełnoekranowy arkusz, a poza nimi alert), a arkusz „displays theNSUserTrackingMarkdownUsageDescriptionstring with support for rich-text elements if you include it in your app’s target configuration in Xcode.” Nowe wywołanie dokłada do tego arkusz w pozostałej części UE, przycisk „Additional Information” oraz parametr, który o niego prosi.4 - Jeden nowy klucz, a stary nadal wymagany.
NSUserTrackingMarkdownUsageDescriptionto opcjonalny Markdown: „bold or italic style,” listy punktowane i podziały akapitów, „but it doesn’t support underline”; nagłówek mówi, że oryginalnyNSUserTrackingUsageDescription„must be in” (musi znaleźć się w) Info.plist także przy nowym wywołaniu.34 - Przycisk „Additional Information” to ani tak, ani nie. Nagłówek Apple: „If the user taps the ‘Additional Information’ button, the prompt dismisses without recording an authorization decision, your
additionalInformationActionruns so you can surface your own privacy information, and the completion handler receivesnotDetermined.” (po jego naciśnięciu monit znika bez zapisania jakiejkolwiek decyzji, uruchamia się przekazana akcja, a completion handler dostajenotDetermined). Kod musi zapytać ponownie.3 - Ponowne pytanie, tylko w UE. „you can reprompt a user via the App Tracking Transparency system prompt one year after the user’s previous choice in your app’s App Tracking Transparency system prompt, regardless of whether that choice was to accept or reject,” czyli rok po poprzednim wyborze, niezależnie od tego, czy była to zgoda, czy odmowa, chyba że dana osoba wyłączyła „Allow Apps to Request to Track,” które w UE nosi nazwę „Allow Apps to Request to Link Your Activity Across Companies.”2
- Co pokazuje symulator. Na symulatorze iPhone 18 Pro na runtimie bety iOS 27.2, z regionem ustawionym na Stany Zjednoczone, Niemcy, Holandię lub Francję, nowe wywołanie z
preferExpandedInterface: truewyświetliło standardowy alert z oryginalnym opisem użycia i bez przycisku „Additional Information”; tak samo zachowały sięfalse, pusta akcja i stare wywołanie, a completion handler czekał na dotknięcie ze statusemnotDetermined. Istnieje jedna droga do natychmiastowegonotDetermined, którą da się odtworzyć na żądanie i którą opisuję niżej: monit wciąż oczekujący z wcześniejszego uruchomienia. Dwa francuskie uruchomienia 20 września również wróciły natychmiast, bez przyczyny, którą umiałbym odnotować, a te same konfiguracje pokazały monit przy kolejnych czystych startach.5
Co się zmieniło, słowami Apple
Apple opisało tę zmianę prozą trzy razy. Najpierw w komunikacie z 16 września, który podaje też powód: „As part of agreements with select European competition authorities, Apple is introducing changes to its App Tracking Transparency framework in the European Union.” (zmiany są częścią porozumień z wybranymi europejskimi organami ochrony konkurencji). Reszta komunikatu podaje regułę i pięć krajów.1 Strona zasad App Store dokłada kształt monitu: „The alternative version of the App Tracking Transparency system prompt has modified formatting and language and provides you the option to use a text button labeled “Additional Information.” This allows you to surface additional information about your request to link user or device data collected from your app with user or device data collected from other companies’ apps, websites, or offline properties for targeted advertising or advertising measurement purposes, or to share user or device data with a data broker.”2 A uwagi do wydania bety iOS i iPadOS 27.2, w sekcji App Tracking Transparency, New Features, streszczają to w jednym zdaniu: AppTrackingTransparency „now supports an alternative expanded prompt and re-prompting on a yearly basis for EU users. The alternative prompt is required for users in France, Germany, Italy, Poland, and Romania.” (obsługuje teraz alternatywny, rozszerzony monit oraz coroczne ponawianie pytania dla użytkowników z UE, a ten alternatywny monit jest wymagany we Francji, w Niemczech, we Włoszech, w Polsce i w Rumunii).6
Strona zasad mówi również, co zostaje bez zmian: obowiązek zapytania przed śledzeniem oraz odpowiedzialność za wszystko, co kryje się za przyciskiem. „Any additional information related to your request or more granular consent controls provided via the text button are entirely your responsibility. However, you cannot access the device’s advertising identifier, or otherwise collect and use device or user data from your app as described in the App Tracking Transparency system prompt, until the user has granted your app permission in that prompt.”2
Apple wydało iOS i iPadOS 27.2 beta 2 (24B5089g) 21 września o 10:00 PT, bez nowego Xcode. Uwagi do wydania bety 2 niosą tę samą linijkę o App Tracking Transparency pod tym samym numerem radar 179504171; cytowany niżej nagłówek SDK się nie zmienił, bo SDK dostarczany jest wewnątrz Xcode 27.2 beta (27B5019j) (11 października: od tego czasu ukazało się Xcode 27.2 beta 2, a jego nagłówka nie czytałem; 14 października: ukazało się też Xcode 27.2 beta 3, 27B5038j, którego nagłówka również nie czytałem, a uwagi do iOS 27.2 beta 4 z 13 października powtarzają wpisy z bety 3 pod tymi samymi numerami; zmiany nazw opisuje przypis 6); a przebiegi w symulatorze opisane w tym wpisie działają na runtimie pierwszej bety, 24B5084k.6
API w SDK 27.2
Xcode 27.2 beta (27B5019j) niesie SDK iOS 27.2 jako build 24B5084k, a nagłówek jego AppTrackingTransparency.framework dokłada jedną metodę klasową obok tej, którą wywołuje się dzisiaj:3
+ (void)requestTrackingAuthorizationUsingExpandedInterface:(BOOL)preferExpandedInterface
additionalInformationAction:(nullable void(^)(void))additionalInformationAction
completionHandler:(void(^)(ATTrackingManagerAuthorizationStatus status))completion API_AVAILABLE(ios(27.2)) API_UNAVAILABLE(macos, tvos, watchos, visionos);
W Swifcie jest to ATTrackingManager.requestTrackingAuthorization(usingExpandedInterface:additionalInformationAction:completionHandler:) (11 października: nagłówek powyżej i ta nazwa w Swifcie pochodzą z pierwszej bety; uwagi Apple do wydania iOS 27.2 beta 3 dwukrotnie zmieniają jej nazwę, najpierw na requestTrackingAuthorization(preferExpandedInterface:...), a potem na requestTrackingAuthorizationPreferringExpandedInterface, nazwę, która zostaje; 26 października: strona dokumentacji tytułuje metodę w Swifcie requestTrackingAuthorization(preferExpandedInterface:additionalInformationAction:completionHandler:), a PreferringExpandedInterface to zapis selektora Objective-C), a strona dokumentacji Apple dla pierwszej nazwy oznaczała tę metodę jako iOS 27.2, iPadOS 27.2 i Mac Catalyst 27.2, wszystko w becie, w odczycie z 19 września (ta strona zwraca teraz 404); strona nowej nazwy, odczytana 26 października, wymienia te same trzy platformy bez oznaczenia bety, a ostatnio zmieniono ją 12 października.7 Komentarz w nagłówku to najpełniejszy opis obu parametrów, jaki Apple opublikowało, i cztery zdania z niego decydują o tym, jak zapisać wywołanie.346
- „Pass
YEStopreferExpandedInterfaceto request the alternative prompt where permitted; passNOto request the original prompt.” A przy samym parametrze: „Note that in France, Germany, Italy, Poland, and Romania, due to legal requirements, only the expanded interface version of the ATT prompt will be available regardless of what is passed in topreferExpandedInterface.” (w tych pięciu krajach dostępna jest wyłącznie wersja rozszerzona, niezależnie od przekazanej wartości). - „If you pass
niltoadditionalInformationAction, this button will not be shown.” (po przekazaniunilprzycisk się nie pojawia). - „If the user taps the ‘Additional Information’ button, the prompt dismisses without recording an authorization decision, your
additionalInformationActionruns so you can surface your own privacy information, and the completion handler receivesnotDetermined.” (monit znika bez zapisania decyzji, a completion handler dostajenotDetermined). - „iOS users may be re-prompted in eligible regions on a periodic basis even after a previous authorization decision. If the user is not eligible to be re-prompted and a previous authorization decision exists, the completion handler is called with that prior decision without showing the prompt.” (w uprawnionych regionach pytanie bywa ponawiane okresowo, a gdy dana osoba nie jest uprawniona i istnieje wcześniejsza decyzja, completion handler zwraca ją bez pokazywania czegokolwiek).
Strona dokumentacji rysuje tabelę regionalną, którą nagłówek jedynie sugeruje. We Francji, w Niemczech, we Włoszech, w Polsce i w Rumunii: „The system displays markdown text you supply via NSUserTrackingMarkdownUsageDescription in a full-page sheet regardless of what you set for preferExpandedInterface, and includes an Additional Information button if you supply an action.” W pozostałej części Unii Europejskiej: „The system displays markdown text in the NSUserTrackingMarkdownUsageDescription, if you supply it. The system displays the full-page sheet if you set preferExpandedInterface to true, and includes an Additional Information button if you supply an action.” Wszędzie indziej: „Outside of the European Union, the system doesn’t use either parameter, and presents a system alert displaying the original NSUserTrackingUsageDescription, which is equivalent to calling requestTrackingAuthorization(completionHandler:).” Strona dodaje warunek tego regionalnego zachowania: urządzenie musi być „located in a specific European Union country and signed in with an Apple Account with a specific EU country or region.” (zlokalizowane w konkretnym kraju Unii Europejskiej i zalogowane na Apple Account z krajem lub regionem z UE).4
Strona starego wywołania, requestTrackingAuthorization(completionHandler:), mówi dziś, że pięć krajów dostaje arkusz również z niego: „In France, Germany, Italy, Poland, and Romania, the system presents a full-page sheet; otherwise, the system prompts the person with an alert.” oraz, w części o właściwościach targetu, „In France, Germany, Italy, Poland, and Romania, the full-page sheet displays the NSUserTrackingMarkdownUsageDescription string with support for rich-text elements if you include it in your app’s target configuration in Xcode.” Ta strona nie podaje żadnej wersji dla arkusza i wymienia metodę przy iOS 14 bez oznaczenia bety, więc próg 27.2 bierze się z uwag do wydania, a nie ze strony. Czytane razem: nowe wywołanie kupuje arkusz w pozostałej części UE, przycisk i wpływ na parametr, a w pięciu krajach arkusz i tak się pojawi.46
Dwa klucze Info.plist
NSUserTrackingUsageDescription nie znika. Uwaga „Important” z nagłówka przy nowej metodzie powtarza stary wymóg słowo w słowo: klucz „must be in” (musi znaleźć się w) Information Property List, a strona dokumentacji nowego klucza mówi, że system sięga po stary, „if your app’s target properties omit this key.” (jeśli właściwości targetu pomijają nowy klucz).34
NSUserTrackingMarkdownUsageDescription to nowość, oznaczona jako iOS 27.2 i iPadOS 27.2 beta. Strona Apple: „The format of the string is Markdown text; you can apply bold or italic style, but it doesn’t support underline. You can include bullet lists and paragraph breaks.” (format to Markdown, z pogrubieniem lub kursywą, listami punktowanymi i podziałami akapitów, ale bez podkreślenia). Klucz jest regionalny tak samo jak monit: używany w pięciu krajach zawsze, gdy jest obecny, zarówno przez stare, jak i przez nowe wywołanie; używany w pozostałej części UE, gdy przekazane zostanie preferExpandedInterface: true; i ignorowany poza UE. Dwie strony Apple opisują przypadek pośredni inaczej: strona metody mówi, że system wyświetla Markdown „if you supply it” (jeśli go dostarczysz), a strona klucza dokłada warunek przekazania true. Strona klucza to odczyt surowszy i to za nim idzie diagram powyżej. Wskazówka Apple na tej stronie jest tą samą, którą daje na stronie oryginalnego klucza śledzenia: „Keep the text of your description short and specific. The system displays your app name in the prompt so you don’t need to include it in the string.”4
Coroczne ponawianie monitu
Strona zasad ustala regułę dla UE: „you can reprompt a user via the App Tracking Transparency system prompt one year after the user’s previous choice in your app’s App Tracking Transparency system prompt, regardless of whether that choice was to accept or reject. A user cannot be re-prompted if they have disabled “Allow Apps to Request to Track” (renamed to “Allow Apps to Request to Link Your Activity Across Companies” in the EU) in their device’s Settings.”2 Nagłówek opisuje ten mechanizm od strony aplikacji, dwukrotnie. Przy starszej metodzie: „In eligible regions, iOS users may be re-prompted after a year has passed since their last decision; otherwise the system remembers the user’s choice and doesn’t prompt again unless the user uninstalls and then reinstalls the app on the device.” Przy nowej: nieuprawniony użytkownik z wcześniejszą decyzją dostaje tę decyzję z powrotem z completion handlera „without showing the prompt,” więc drugie wywołanie jest bezpieczne, a o tym, czy monit się pojawi, decyduje system, nie kod aplikacji.3 Czego nie daje żaden z tych dokumentów, to sposobu na sprawdzenie przed wywołaniem, czy dana osoba jest uprawniona: wywołanie jest zapytaniem.
Co robi symulator bety 27.2
Zbudowałem jednoplikową sondę w SwiftUI wobec SDK iPhoneSimulator 27.2, z obydwoma kluczami w jej Info.plist: NSUserTrackingUsageDescription z wartością „Probe: the standard usage description.” oraz NSUserTrackingMarkdownUsageDescription z pogrubionym słowem, frazą kursywą i dwupunktową listą. Uruchomiłem ją na symulatorze iPhone 18 Pro na runtimie bety iOS 27.2 (24B5084k), restartując symulator przed każdym przebiegiem i ustawiając region przez globalną preferencję AppleLocale. Sześć przebiegów 19 września: Stany Zjednoczone, Niemcy i Holandia z preferExpandedInterface: true oraz akcją; Niemcy z false; Francja z true i bez akcji; Niemcy ze starym wywołaniem.5
19 września każdy przebieg dał to samo: standardowy alert, zatytułowany „Allow “ATTProbe” to track your activity across other companies’ apps and websites?”, z oryginalnym opisem użycia, z „Ask App Not to Track” i „Allow”, bez trzeciego przycisku. Tekst w Markdownie nie pojawił się ani razu, żaden completion handler nie zadziałał w ciągu szesnastosekundowego nagrania, a w pięciu rozszerzonych przebiegach trackingAuthorizationStatus wskazywał notDetermined przy każdym trzysekundowym sprawdzeniu przez dwanaście sekund; przebieg ze starym wywołaniem zapisał swoją linię mode=legacy i nic po niej, i czekał tak samo.5 Dokładnie to przewiduje strona dokumentacji Apple dla urządzenia, które nie znajduje się w UE, a ustawienie regionu w symulatorze to ustawienie językowe, nie lokalizacja: arkusz, tekst w Markdownie i przycisk pozostają testem na urządzeniu z Apple Account z regionu UE.
Powtórzone 20 września, po restarcie Maca, te same sześć przebiegów pokazało monit dla Stanów Zjednoczonych, Niemiec i Holandii tak jak wcześniej, ale przebieg francuski zwrócił notDetermined do completion handlera w tej samej sekundzie co swoje żądanie i nie pokazał żadnego alertu. Dwa kolejne francuskie uruchomienia tego ranka zrobiły to samo, a trzecie pokazało monit; z trzech natychmiastowych powrotów tylko ten o 7:23 zbiega się z czymkolwiek, co zapisały pliki, czyli z drugim skryptem przeinstalowującym sondę pod spodem, a te o 7:21 i 7:26 nie mają żadnej odnotowanej przyczyny. Gdy nic innego nie dotykało symulatora, trzy kolejne uruchomienia po czystym starcie, Francja z akcją, Francja bez niej i Stany Zjednoczone, pokazały monit i czekały. Te same francuskie konfiguracje pokazały więc monit przy późniejszych czystych startach i nie mam żadnej reguły o Francji do zaraportowania, tylko przestrogę: natychmiastowe notDetermined bez alertu na symulatorze z betą to wynik, który trzeba powtórzyć po czystym starcie, zanim się w niego uwierzy.5

Symulator bety iOS 27.2 z regionem ustawionym na Niemcy, po wywołaniu z rozszerzonym interfejsem 19 września: standardowy alert, oryginalny opis, dwa przyciski. To jedyny eksport wykonany przed restartem, który zabrał resztę plików z tamtego dnia.
Ślepa uliczka, którą da się odtworzyć na żądanie, to oczekujący monit. Wystarczy uruchomić sondę, zostawić alert bez odpowiedzi, odinstalować i zainstalować aplikację ponownie, a potem uruchomić ją jeszcze raz: rozszerzone wywołanie z drugiego uruchomienia zwróciło notDetermined do completion handlera w tej samej sekundzie co swoje żądanie, podczas gdy alert nadal był na ekranie, a trzecie uruchomienie ze starym wywołaniem zrobiło to samo, legacy-request status=0 (notDetermined) w ciągu sekundy. To przypadek opisany w nagłówku: „The authorization prompt doesn’t display if another permission request is pending user confirmation. Concurrent requests aren’t preserved by iOS,” (monit się nie wyświetla, gdy inne żądanie uprawnień czeka na potwierdzenie, a iOS nie zachowuje równoległych żądań), po czym następuje polecenie sprawdzenia, czy trackingAuthorizationStatus ma wartość notDetermined, „to determine if you need to make an additional call,” a strona starego wywołania wymienia ten przypadek wśród sytuacji, w których system uruchamia completion handler bez monitu: „An existing permission request is pending.”345 Czysty start to czyści. Jeśli aplikacja pyta z więcej niż jednego miejsca albo ponawia pytanie według harmonogramu, to właśnie natychmiastowe notDetermined dostanie drugi z wywołujących.
Co wdrożyć, krok po kroku
- Zachować
NSUserTrackingUsageDescription. Klucz nadal jest wymagany i to jego tekst zobaczy każdy użytkownik spoza UE oraz każdy użytkownik z UE bez klucza markdownowego.34 - Dodać
NSUserTrackingMarkdownUsageDescriptionz tą samą prośbą w krótkim Markdownie: pogrubienie lub kursywa, punkty, podziały akapitów, żadnego podkreślenia, bez nazwy aplikacji.4 - Uzależnić nowe wywołanie od dostępności i zostawić stare jako wariant zapasowy: na iOS 27.2 i nowszym wywoływać
requestTrackingAuthorization(usingExpandedInterface:additionalInformationAction:completionHandler:)(11 października: uwagi Apple do wydania iOS 27.2 beta 3 dwukrotnie zmieniają jej nazwę, najpierw narequestTrackingAuthorization(preferExpandedInterface:...), a potem narequestTrackingAuthorizationPreferringExpandedInterface, nazwę, która zostaje; 26 października: strona dokumentacji Apple podaje sygnaturę w Swifcie jakorequestTrackingAuthorization(preferExpandedInterface:additionalInformationAction:completionHandler:); poniższy fragment używa pierwszej nazwy i nie został skompilowany z SDK 27.2 RC, którego nie ma na tym Macu), a wcześniejrequestTrackingAuthorization(completionHandler:). Przekazanietruedaje arkusz w pozostałej części UE, a pięć krajów i tak ignoruje ten parametr. Postać, która przechodzi kontrolę typów wobec SDK 27.2 beta 1 przy progu iOS 26:3456
#if os(iOS)
if #available(iOS 27.2, *) {
ATTrackingManager.requestTrackingAuthorization(usingExpandedInterface: true,
additionalInformationAction: showPrivacyDetails) { status in
handle(status)
}
} else {
ATTrackingManager.requestTrackingAuthorization { status in handle(status) }
}
#endif
- Zdecydować w sprawie przycisku. Akcję warto przekazać tylko wtedy, gdy jest strona albo ekran do pokazania. Gdy akcja się uruchomi, należy potraktować status jako
notDetermined, pokazać własne informacje i, słowami strony zasad, „you can redirect the user back to the App Tracking Transparency system prompt for your app to ensure their choice is recorded,” (można odesłać daną osobę z powrotem do systemowego monitu, aby jej wybór został zapisany), ale „you should not redirect users to your ATT prompt if they have opted out of all relevant legal consent choices in the screen or page surfaced.”23 - Zaplanować ponowne pytanie jako wywołanie, nie jako minutnik. Ponowne wywołanie w UE jest sposobem na sprawdzenie, czy minął rok; completion handler zwraca wcześniejszą decyzję, gdy dana osoba nie jest uprawniona.23
- Testować na urządzeniu z kontem z regionu UE. Ilekroć symulator pokazał monit, w każdym regionie i po czystych startach, był to standardowy alert i nigdy arkusz, a warunkiem Apple jest lokalizacja urządzenia plus region Apple Account, więc pełnoekranowy arkusz pozostaje testem na urządzeniu.45
- Sprawdzić target dla Maca. Nagłówek oznacza metodę jako niedostępną na macOS, tvOS, watchOS i visionOS, więc wspólne miejsce wywołania potrzebuje
#if os(iOS)wokół wywołania iif #available(iOS 27.2, *)w środku; samo sprawdzenie dostępności nadal nie przechodzi kompilacji, z komunikatem'requestTrackingAuthorization(usingExpandedInterface:additionalInformationAction:completionHandler:)' is unavailable in macOS, co odnotowuje przypis 5 (11 października: komunikat wymienia metodę z pierwszej bety; uwagi Apple do wydania iOS 27.2 beta 3 dwukrotnie zmieniają jej nazwę, najpierw narequestTrackingAuthorization(preferExpandedInterface:...), a potem narequestTrackingAuthorizationPreferringExpandedInterface, nazwę, która zostaje; 26 października: to selektor Objective-C, a strona dokumentacji Apple podaje metodę w SwifcierequestTrackingAuthorization(preferExpandedInterface:additionalInformationAction:completionHandler:)7). Wpis Mac Catalyst 27.2 na stronie dokumentacji iAPI_UNAVAILABLE(macos)z nagłówka opisują tę samą linię z dwóch stron: dla#if os(iOS)Catalyst liczy się jako iOS.3456
Często zadawane pytania
Czy trzeba przyjąć alternatywny monit?
We Francji, w Niemczech, we Włoszech, w Polsce i w Rumunii alternatywny monit jest jedyną wersją dostępną dla aplikacji tam dystrybuowanych, zgodnie z komunikatem Apple, a na 27.2 dostaje się go z obu wywołań: nowe pokazuje tam pełnoekranowy arkusz „regardless of what you set for preferExpandedInterface,” a strona Apple dla starego wywołania mówi „In France, Germany, Italy, Poland, and Romania, the system presents a full-page sheet; otherwise, the system prompts the person with an alert,” z kluczem markdownowym pokazywanym „if you include it in your app’s target configuration in Xcode.” Przyjęcie nowego wywołania daje arkusz w pozostałej części UE, przycisk „Additional Information” oraz wpływ na parametr.1346
Czy zmienia się to, kiedy trzeba prosić o zgodę?
Nie. Apple: „The requirements for when you must seek permission to track users will remain the same.” (wymagania dotyczące tego, kiedy trzeba prosić o zgodę na śledzenie, pozostają bez zmian).1
Czy klucz markdownowy zastępuje NSUserTrackingUsageDescription?
Nie. Oryginalny klucz nadal jest wymagany przy obu wywołaniach, a system sięga po niego zawsze, gdy klucza markdownowego brakuje albo gdy urządzenie znajduje się poza UE.34
Czy można zapytać ponownie po odmowie?
W UE tak, rok po poprzednim wyborze, „regardless of whether that choice was to accept or reject,” chyba że dana osoba wyłączyła ustawienie, które Apple przemianowało w UE na „Allow Apps to Request to Link Your Activity Across Companies.”2
Czy nowe API istnieje na macOS albo visionOS?
Nie. Nagłówek SDK 27.2 oznacza je jako API_UNAVAILABLE(macos, tvos, watchos, visionos), a strona dokumentacji wymienia iOS, iPadOS i Mac Catalyst 27.2.34
Powiązane na tej stronie: wpis o informacjach o wydaniu iOS 27 śledzi kompilacje bety 27.2, na których opiera się ten tekst, Privacy Manifest od podszewki opisuje drugą deklarację, którą Apple czyta przy wysyłce do sklepu, wpis o deklaracji mediów społecznościowych w App Store to druga wrześniowa zmiana zasad, zbiorczy wpis o Xcode 27 ma harmonogram SDK i wysyłki, wpis o nakazie scen w UIKit to druga wymuszona zmiana w tym cyklu SDK, a wpis o wycofaniu On Demand Resources opisuje termin, który zapada przed nim.
Źródła
-
Apple, „Updates to App Tracking Transparency in the European Union”, aktualności dla deweloperów, 16 września 2026, cytowane. ↩↩↩↩↩
-
Apple, User privacy and data use, sekcja „ATT in the European Union” oraz pytanie „Can I provide additional information and consent controls with my app’s ATT prompt implementation,” pobrane 19 września 2026 roku, cytowane. ↩↩↩↩↩↩↩↩
-
AppTrackingTransparency.framework/Headers/ATTrackingManager.hw SDK iPhoneOS 27.2 (ProductBuildVersion24B5084k,ProductVersion27.2) wewnątrz Xcode 27.2 beta (27B5019j), odczytany 19 września 2026 roku: deklaracjarequestTrackingAuthorizationUsingExpandedInterface:additionalInformationAction:completionHandler:zAPI_AVAILABLE(ios(27.2)) API_UNAVAILABLE(macos, tvos, watchos, visionos)oraz jej komentarz dokumentacyjny, cytowane; komentarz starszej metody o ponawianiu monitu i o oczekujących żądaniach, cytowany. 11 października 2026 roku: uwagi Apple do wydania iOS 27.2 beta 3 dwukrotnie zmieniają nazwę tej metody, najpierw narequestTrackingAuthorization(preferExpandedInterface:...), a potem narequestTrackingAuthorizationPreferringExpandedInterface, nazwę, która zostaje (przypis 6); nie czytałem nagłówka, który deklarowałby nową nazwę. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Apple, requestTrackingAuthorization(usingExpandedInterface:additionalInformationAction:completionHandler:) (od 26 października 2026 strona zwraca 404; jej treść jest cytowana w brzmieniu z 19 września) oraz NSUserTrackingMarkdownUsageDescription, JSON dokumentacji pobrany 19 września 2026 roku: dostępność platform iOS 27.2, iPadOS 27.2 i Mac Catalyst 27.2 (metoda) oraz iOS 27.2 i iPadOS 27.2 (klucz), wszystko oznaczone jako beta; sekcje „Display a full-page sheet” i „Discussion”, cytowane. Apple, requestTrackingAuthorization(completionHandler:), JSON dokumentacji pobrany 21 września 2026 roku: dostępność platform iOS 14.0, iPadOS 14.0, Mac Catalyst 14.0, macOS 11.0, tvOS 14.0 i visionOS 1.0 bez oznaczenia bety; zdanie z Discussion o pięciu krajach, zdanie „Configure the app’s target properties” o kluczu markdownowym oraz pozycja o oczekującym żądaniu na liście przypadków, w których „the system doesn’t display the prompt,” cytowane. 11 października 2026 roku: tytuł pierwszego odnośnika to pierwsza nazwa metody; uwagi Apple do wydania iOS 27.2 beta 3 dwukrotnie zmieniają jej nazwę, najpierw na
requestTrackingAuthorization(preferExpandedInterface:...), a potem narequestTrackingAuthorizationPreferringExpandedInterface, nazwę, która zostaje (przypis 6). Strony dokumentacji nie pobrano ponownie 11 października; 26 października zwróciła 404 (przypis 7). ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Przebiegi autora na macOS 26.6.2 (25G83), 19 i 20 września 2026 roku. ATTProbe: jednoplikowa aplikacja SwiftUI na cyklu życia
AppiWindowGroup, zbudowana poleceniemxcrun swiftc -sdk <iPhoneSimulator27.2.sdk> -target arm64-apple-ios26.0-simulator -parse-as-librarypod Xcode 27.2 beta (27B5019j), z plikiem Info.plist zawierającymNSUserTrackingUsageDescription„Probe: the standard usage description.” orazNSUserTrackingMarkdownUsageDescription„Probe: Markdown description with a bullet list:” i dwa elementy listy. Wcześniejsza wersja tej samej sondy w UIKit, bez manifestu scen, zbudowana wobec tego samego SDK, przerywała działanie przy starcie zEXC_BREAKPOINT, zanim doszła do żądania; zastąpiłem ją, zamiast badać przyczynę. Urządzenie: symulator iPhone 18 Pro utworzony poleceniemsimctl createnacom.apple.CoreSimulator.SimRuntime.iOS-27-2(24B5084k), sterowany przezsimctlz Xcode 27.2 beta; region ustawiany poleceniemsimctl spawn <udid> defaults write "Apple Global Domain" AppleLocale -string <locale>;simctl shutdownisimctl bootprzed każdym przebiegiem; aplikacja uruchamiana przezsimctl launch --console-ptyz przechwytywaniem jej liniiprint; zrzut ekranu przezsimctl io <udid> screenshotsiedem sekund po uruchomieniu, nagranie kończone dziewięć sekund później. Przebiegi:en_USrozszerzony z akcją;de_DErozszerzony z akcją;de_DEze starym wywołaniemrequestTrackingAuthorization(completionHandler:);de_DEzpreferExpandedInterface: false;nl_NLrozszerzony z akcją;fr_FRrozszerzony z pustą akcją. 19 września w każdym przebiegu log wypisałregion=<code> status-before=0i żadnej linii zakończenia w ciągu szesnastosekundowego nagrania; w pięciu rozszerzonych przebiegach wypisał takżestatus-now=0po trzech, sześciu, dziewięciu i dwunastu sekundach, czyli sprawdzenie, którego gałąź starego wywołania w sondzie nie wykonuje; każdy zrzut ekranu pokazał standardowy alert (te pliki, podobnie jak pliki wcześniejszej serii z 19 września, która jako pierwsza pokazała zachowanie oczekującego monitu, nie przetrwały restartu Maca, który wyczyścił tymczasowy katalog sesji, więc wyniki z 19 września są tu odnotowane na podstawie odczytanego wtedy wyjścia konsoli). 20 września, pierwsza seria, ten sam skrypt z czystym startem przed każdym przebiegiem:en_US7:16:37,de_DE7:17:42, stare wywołanie zde_DE7:18:42,de_DEzfalse7:19:33 inl_NL7:20:26, każdy bez linii zakończenia i zstatus-now=0przy każdym sprawdzeniu tam, gdzie sonda odpytuje, a każdy zrzut ekranu ze standardowym alertem;fr_FRbez akcji, 7:21:04, wypisałexpanded-request status=0 (notDetermined)o 7:21:05, w tej samej sekundzie co swoją linięmode=, a jego zrzut pokazuje własny log sondy i żadnego alertu. Drugi symulator, urządzenie iPhone Duo, wystartował o 7:13 i działał przez całą tę serię; nic w plikach nie odnotowuje niczego innego, co dotykałoby któregokolwiek z symulatorów w jej trakcie. Druga seria, od 7:23 do 7:27, przez pierwsze trzy uruchomienia nachodząca na pierwsze podejście do sekwencji z oczekującym monitem, które dwukrotnie zawiodło z błędami symulatora:fr_FRbez akcji, 7:23:57, natychmiastowenotDetermined;fr_FRz akcją, 7:24:09, uruchomiony przez tamten drugi skrypt, pokazał monit bez linii zakończenia;de_DEbez akcji, 7:24:52, pokazał monit;fr_FRz akcją, 7:26:03, natychmiastowenotDetermined;en_USbez akcji, 7:27:43, pokazał monit; uruchomieniefr_FRo 7:23:09 zawiodło, gdy symulator się wyłączał, a log z 7:23:57 kończy się na szóstej sekundzie, bo tamten drugi skrypt przeinstalował sondę. Wymieniam je dla kompletności i nie przypisuję im żadnej wagi. Trzecia seria, po jednym przebiegu naraz, bez niczego innego dotykającego symulatora i z czystym startem przed każdym:fr_FRz akcją 7:40:06,fr_FRbez akcji 7:40:45 i 7:41:22 z ciągiem ustawień regionalnychus_US(sonda wypisałaregion=US), wszystkie pokazały monit, bez linii zakończenia i zstatus-now=0przy każdym sprawdzeniu. Przypadek oczekującego monitu, ten sam skrypt, jeden start:de_DEo 7:42:00 pokazał monit bez linii zakończenia; posimctl uninstallisimctl installz tym alertem pozostawionym bez odpowiedzi uruchomienie o 7:42:18 wypisałoexpanded-request status=0 (notDetermined)o 7:42:19, a jego zrzut ekranu pokazuje alert na ekranie; trzecie uruchomienie ze starym wywołaniem o 7:42:40 wypisałolegacy-request status=0 (notDetermined)o 7:42:41. Fragment z kroku 3, zshowPrivacyDetailsihandle(_:)jako funkcjami zastępczymi, przeszedłswiftc -typecheckwobec SDK iPhoneSimulator 27.2 przy-target arm64-apple-ios26.0-simulator; ten sam plik z usuniętymi liniami#if os(iOS), skompilowany wobec SDK macOS z Xcode 27.2 beta przy-target arm64-apple-macos15.0, zawiódł z komunikatemerror: 'requestTrackingAuthorization(usingExpandedInterface:additionalInformationAction:completionHandler:)' is unavailable in macOS. 11 października 2026 roku: te przebiegi i kontrola typów używają pierwszej nazwy metody; uwagi Apple do wydania iOS 27.2 beta 3 dwukrotnie zmieniają jej nazwę, najpierw narequestTrackingAuthorization(preferExpandedInterface:...), a potem narequestTrackingAuthorizationPreferringExpandedInterface, nazwę, która zostaje (przypis 6). Niczego z tego nie uruchomiono ponownie z nową nazwą. ↩↩↩↩↩↩↩↩↩ -
Apple, iOS & iPadOS 27.2 Beta Release Notes, pobrane przez endpoint JSON dokumentacji 17 i 19 września 2026 roku, App Tracking Transparency, New Features, cytowane. Pobrane ponownie 21 września 2026 roku, gdy strona nosiła tytuł „iOS & iPadOS 27.2 Beta 2 Release Notes”: ta sama linijka pod 179504171, te same sekcje, Overview, App Tracking Transparency, Health, Shortcuts i StoreKit Testing in Xcode. Apple, Releases, kanał RSS pobrany 21 września 2026 roku: „iOS 27.2 beta 2 (24B5089g)” i „iPadOS 27.2 beta 2 (24B5089g)” z datą Mon, 21 Sep 2026 10:00:00 PDT, a o tej samej godzinie macOS 27.2 beta 2 (26B5091g), tvOS 27.2 beta 2 (24K5093g), visionOS 27.2 beta 2 (24N5093f) i watchOS 27.2 beta 2 (24S5091f); najnowszy wpis o Xcode to nadal „Xcode 27.1 beta (27A9269)” z 18 września. 11 października 2026 roku: ten sam adres URL, pobrany ponownie i zatytułowany teraz „iOS & iPadOS 27.2 Beta 3 Release Notes” (build 24B5099f, w kanale wydań z datą 5 października), zachowuje linijkę New Features pod 179504171 i dodaje dwa Resolved Issues w App Tracking Transparency: „Fixed: The new
requestTrackingAuthorization(usingExpandedInterface:additionalInformationAction:completionHandler:)API is renamed torequestTrackingAuthorization(preferExpandedInterface:...). (187149729)” oraz „Fixed: The newrequestTrackingAuthorization(preferExpandedInterface:...)API is renamed torequestTrackingAuthorizationPreferringExpandedInterface:…). (187610745)” (każdy z wpisów ogłasza zmianę nazwy nowego API). Apple zapisuje trzecią nazwę w połowie w Objective-C, a w połowie w Swift i skraca drugą oraz trzecią, więc uwagi nie podają pełnej sygnatury żadnej z nich i nie mówią, czy wcześniejsze nazwy pozostają jako przestarzałe warianty. Kanał wydań pobrany tego samego dnia nie wymienia żadnego Xcode 27.2 po becie 2 (27B5028f) z 28 września. Kanał pobrany 15 października 2026 roku o 04:36 UTC (14 października, 21:36 czasu pacyficznego) dodaje „iOS 27.2 beta 4 (24B5110a)” z datą Tue, 13 Oct 2026 10:00:00 PDT oraz „Xcode 27.2 beta 3 (27B5038j)” z datą Wed, 14 Oct 2026 10:00:00 PDT; iOS & iPadOS 27.2 Beta 4 Release Notes, pobrane 15 października 2026 roku o 04:38 UTC (14 października, 21:38 czasu pacyficznego), zawierają funkcję App Tracking Transparency pod 179504171 i obie zmiany nazw pod 187149729 i 187610745, bez zmian względem strony bety 3; nagłówek SDK z bety 3 pozostaje nieprzeczytany, podobnie jak nagłówek z bety 2. ↩↩↩↩↩↩↩↩↩ -
Apple, requestTrackingAuthorization(preferExpandedInterface:additionalInformationAction:completionHandler:), pobrane przez punkt końcowy JSON dokumentacji 26 października 2026, serwowane z nagłówkiem Last-Modified Mon, 12 Oct 2026 11:18:00 GMT: dostępność iOS 27.2, iPadOS 27.2 i Mac Catalyst 27.2 bez flagi beta; deklaracje
class func requestTrackingAuthorization(preferExpandedInterface: Bool, additionalInformationAction: (() -> Void)?, completionHandler completion: @escaping @Sendable (ATTrackingManager.AuthorizationStatus) -> Void)orazclass func requestTrackingAuthorization(preferExpandedInterface: Bool, additionalInformationAction: (() -> Void)?) async -> ATTrackingManager.AuthorizationStatus. Strona ATTrackingManager, pobrana w tej samej godzinie, wymienia tę metodę irequestTrackingAuthorization(completionHandler:), a żadnej innej metody żądania; punkt końcowy JSON dlarequesttrackingauthorization(usingexpandedinterface:additionalinformationaction:completionhandler:)zwrócił 404. Apple, iOS & iPadOS 27.2 Release Notes, pobrane 26 października 2026 (Last-Modified Mon, 26 Oct 2026 14:18:44 GMT): App Tracking Transparency, New Features (179504171, bez zmian) i Resolved Issues, „Fixed: The newrequestTrackingAuthorization(usingExpandedInterface:additionalInformationAction:completionHandler:)API is renamed torequestTrackingAuthorization(preferExpandedInterface:...). (187149729)” oraz „Fixed: The newrequestTrackingAuthorizationPreferExpandedInterface:...API is renamed torequestTrackingAuthorizationPreferringExpandedInterface:.... (187610745)”. Apple, Releases, kanał RSS pobrany 26 października 2026: „iOS 27.2 (24B119)” i „iPadOS 27.2 (24B119)” z datą Mon, 26 Oct 2026 10:00:00 PDT; najnowszą pozycją Xcode jest „Xcode 27.2 RC (27B48)” z 19 października.ATTrackingManager.hw SDK iOS 27.2 (24B5084k) z Xcode 27.2 beta (27B5019j), przeczytany ponownie 26 października 2026, nadal deklarujerequestTrackingAuthorizationUsingExpandedInterface:additionalInformationAction:completionHandler:zAPI_AVAILABLE(ios(27.2)); Xcode 27.2 RC nie jest zainstalowane na tym Macu. ↩↩↩↩↩