Tüm Yazılar
KategoriiOS
Okuma Süresi
16 dk okuma
Yayın Tarihi
...
Kelime Sayısı
3.075kelime

Kahveni hazırla - bu içerikli bir makale!

Privacy Manifests (PrivacyInfo.xcprivacy), required reason API, SDK declarations, App Tracking Transparency best practices ve 2026'daki App Store yeni gereklilikleri.

iOS Privacy Manifests ve App Tracking: 2026 Compliance Rehberi

# iOS Privacy Manifests ve App Tracking: 2026 Compliance Rehberi

Apple'ın privacy-first yaklaşımı her yıl yeni compliance gereklilikler getiriyor. 2023'te başlayan Privacy Manifests zorunluluğu, 2024'te SDK manifest kontrolüyle genişledi, 2025'te binary validation eklendi ve 2026'da App Store submission süreci daha da katılaştı. Artık bir app submit etmek için sadece kodu yazmak yetmiyor — kullandığın her API'nin neden kullanıldığını, hangi verileri topladığını ve hangi third-party SDK'ların hangi domain'lere bağlandığını beyanda bulunman gerekiyor.

Bu rehber, Privacy Manifests yapısını, Required Reason API kategorilerini, SDK manifest composition sürecini ve ATT (App Tracking Transparency) best practice'lerini 2026 güncel durumla anlatıyor. App Store rejection'dan kaçınmak için gerçekten ne gerektiğini, neyin yanlış yapıldığını ve production deneyiminden öğrenilenleri paylaşıyor.

2026'da yeni gelen gereklilik: App Store Connect artık third-party SDK binary'lerini statik analiz ile tarayıp manifest'te declare edilmemiş API kullanımlarını otomatik tespit ediyor. Bu da demek oluyor ki dependency'lerini körce ekleme dönemi bitti — her CocoaPod, her SPM package, her XCFramework inceleme altında.

💡 Pro Tip: App Store'a submit etmeden önce xcrun privacy-manifest CLI aracını çalıştır (Xcode 15.3+). Bu araç, uygulamanın kullandığı Required Reason API'ları otomatik tespit eder ve PrivacyInfo.xcprivacy ile karşılaştırır. CI pipeline'ına ekle — submission öncesi otomatik uyarı alırsın.

İçindekiler


Privacy Manifest Nedir

Privacy Manifest, bir iOS uygulamasının veya SDK'ının hangi privacy-sensitive API'ları kullandığını ve neden kullandığını beyan ettiği yapılandırma dosyasıdır. PrivacyInfo.xcprivacy adıyla proje root'una veya SDK bundle'ına eklenir.

Neden zorunlu? Apple, üçüncü taraf SDK'ların uygulama geliştiricilerin habersizce privacy-sensitive API kullanmasının önüne geçmek istiyor. "Fingerprinting" olarak adlandırılan — kullanıcıyı tanımlamak için sistem bilgilerini birleştirme — yöntemi bu sayede engellenmeye çalışılıyor.

Kim için geçerli?

  • Her iOS/iPadOS/macOS/tvOS/watchOS uygulaması
  • App Store'da dağıtılan SDK'lar (CocoaPods, SPM, XCFramework)
  • Third-party framework vendor'ları

Hangi durumlarda rejection alırsın?

  • Required Reason API kullanıyorsun ama manifest'te declare etmemişsin
  • Declare ettiğin reason, gerçek kullanım amacıyla eşleşmiyor
  • Kullandığın third-party SDK'nın kendi manifest'i eksik veya yanlış
  • Tracking domain beyan edilmemiş ama SDK o domain'e bağlanıyor

PrivacyInfo.xcprivacy Yapısı

PrivacyInfo.xcprivacy bir property list (plist) dosyası. Xcode'da "Privacy Manifest File" template'i ile oluşturulur.

xml
1
2
3 "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4
5
6
7 NSPrivacyTracking
8
9 
10
11 NSPrivacyTrackingDomains
12
13
14
15 
16
17 NSPrivacyAccessedAPITypes
18
19
20 NSPrivacyAccessedAPIType
21 NSPrivacyAccessedAPICategoryUserDefaults
22 NSPrivacyAccessedAPITypeReasons
23
24 CA92.1
25
26
27
28 NSPrivacyAccessedAPIType
29 NSPrivacyAccessedAPICategoryFileTimestamp
30 NSPrivacyAccessedAPITypeReasons
31
32 C617.1
33
34
35
36 
37
38 NSPrivacyCollectedDataTypes
39
40
41 NSPrivacyCollectedDataType
42 NSPrivacyCollectedDataTypeEmailAddress
43 NSPrivacyCollectedDataTypeLinked
44
45 NSPrivacyCollectedDataTypeTracking
46
47 NSPrivacyCollectedDataTypePurposes
48
49 NSPrivacyCollectedDataTypePurposeAppFunctionality
50
51
52
53
54

Dosya konumu:

  • App: [AppName]/PrivacyInfo.xcprivacy (target'ın root'unda)
  • SDK: Framework/XCFramework bundle içinde

Xcode'da ekleme:

  1. File → New → File from Template → iOS → Privacy Manifest
  2. Target membership'te uygulamanı seç
  3. Xcode otomatik privacy nutrition label güncelliyor

NSPrivacyAccessedAPITypes: 4 Kategori

Apple, "Required Reason API" olarak 4 ana kategori tanımladı. Bu API'lara erişmek için geçerli bir reason kodu declare etmek zorundasın.

Kategori 1: UserDefaults

NSPrivacyAccessedAPICategoryUserDefaultsUserDefaults API'sına erişim.

swift
1// Bu kullanımlar manifest gerektirir:
2UserDefaults.standard.set(value, forKey: key)
3UserDefaults.standard.value(forKey: key)
4UserDefaults(suiteName: "group.com.example")
5 
6// Geçerli reason kodları:
7// CA92.1 — Sadece bu uygulamanın kendi state'ini yönetmek için
8// 1C8F.1 — App group container paylaşımı için
9// C56D.1 — Kullanıcı tarafından talep edilen içerik sağlamak için
xml
1
2 NSPrivacyAccessedAPIType
3 NSPrivacyAccessedAPICategoryUserDefaults
4 NSPrivacyAccessedAPITypeReasons
5
6 CA92.1
7
8

Kategori 2: File Timestamp

NSPrivacyAccessedAPICategoryFileTimestamp — Dosya oluşturma/değiştirme tarihine erişim.

swift
1// Bu kullanımlar manifest gerektirir:
2let attributes = try FileManager.default.attributesOfItem(atPath: path)
3let modDate = attributes[.modificationDate]
4let url = URL(fileURLWithPath: path)
5let resourceValues = try url.resourceValues(forKeys: [.contentModificationDateKey])
xml
1
2 NSPrivacyAccessedAPIType
3 NSPrivacyAccessedAPICategoryFileTimestamp
4 NSPrivacyAccessedAPITypeReasons
5
6
7 C617.1
8
9

Kategori 3: System Boot Time

NSPrivacyAccessedAPICategorySystemBootTime — Cihazın ne zaman başlatıldığı bilgisi. Fingerprinting için kullanılabildiğinden en kısıtlı kategori.

swift
1// Bu kullanımlar manifest gerektirir:
2ProcessInfo.processInfo.systemUptime
3clock_gettime(CLOCK_MONOTONIC, &timespec)
4mach_absolute_time()
5// CFAbsoluteTimeGetCurrent() NOT burada değil, sadece boot-time relative
xml
1
2 NSPrivacyAccessedAPIType
3 NSPrivacyAccessedAPICategorySystemBootTime
4 NSPrivacyAccessedAPITypeReasons
5
6
7 35F9.1
8
9

Kategori 4: Disk Space

NSPrivacyAccessedAPICategoryDiskSpace — Kullanılabilir disk alanı bilgisi.

swift
1// Bu kullanımlar manifest gerektirir:
2let values = try URL(fileURLWithPath: "/").resourceValues(
3 forKeys: [.volumeAvailableCapacityForImportantUsageKey]
4)
5let available = values.volumeAvailableCapacityForImportantUsage
xml
1
2 NSPrivacyAccessedAPIType
3 NSPrivacyAccessedAPICategoryDiskSpace
4 NSPrivacyAccessedAPITypeReasons
5
6
7 E174.1
8
9

NSPrivacyCollectedDataTypes

Uygulamanın topladığı tüm veri türleri declare edilmeli. Bu, App Store privacy nutrition label'ını oluşturur.

xml
1NSPrivacyCollectedDataTypes
2
3
4
5 NSPrivacyCollectedDataType
6 NSPrivacyCollectedDataTypeEmailAddress
7
8 NSPrivacyCollectedDataTypeLinked
9
10
11 NSPrivacyCollectedDataTypeTracking
12
13
14 NSPrivacyCollectedDataTypePurposes
15
16 NSPrivacyCollectedDataTypePurposeAppFunctionality
17
18
19 
20
21
22 NSPrivacyCollectedDataType
23 NSPrivacyCollectedDataTypeProductInteraction
24 NSPrivacyCollectedDataTypeLinked
25
26 NSPrivacyCollectedDataTypeTracking
27
28 NSPrivacyCollectedDataTypePurposes
29
30 NSPrivacyCollectedDataTypePurposeAnalytics
31
32
33

Ana veri kategorileri:

Kategori
Key
Örnek
İletişim Bilgisi
`NSPrivacyCollectedDataTypeEmailAddress`
E-posta
Sağlık
`NSPrivacyCollectedDataTypeHealth`
Kalp atışı
Konum
`NSPrivacyCollectedDataTypePreciseLocation`
GPS
İdentifierlar
`NSPrivacyCollectedDataTypeDeviceID`
IDFA
Kullanım Verileri
`NSPrivacyCollectedDataTypeProductInteraction`
Tıklamalar
Teşhis
`NSPrivacyCollectedDataTypeCrashData`
Crash log

NSPrivacyTrackingDomains

Eğer NSPrivacyTracking = true ise, tracking için kullanılan tüm domain'ler listelenmelidir. ATT permission alınmadan bu domain'lere bağlantı iOS tarafından engellenir.

xml
1NSPrivacyTracking
2
3NSPrivacyTrackingDomains
4
5 analytics.yourdomain.com
6 track.adnetwork.com
7 events.mmprovider.com
8

Tracking domain nedir? Apple'ın tanımına göre, kullanıcının uygulamalar ve web siteleri arasında takip edilmesi amacıyla kullanılan domain. Şüpheli durumlarda tracking olarak declare et — yanlış bir false declaration, App Review'dan geçse bile gelecekte rejection sebebi olur.

swift
1// ATT durumuna göre tracking domain davranışı
2import AppTrackingTransparency
3 
4func checkTrackingPermission() async {
5 // iOS, ATT izni olmadan tracking domain'lere bağlantıyı engeller
6 let status = ATTrackingManager.trackingAuthorizationStatus
7 
8 switch status {
9 case .authorized:
10 // Tracking domain'ler erişilebilir, IDFA kullanılabilir
11 enableFullAnalytics()
12 case .denied, .restricted:
13 // Tracking domain'ler bloklu — sadece non-tracking analytics
14 enablePrivacyAnalytics()
15 case .notDetermined:
16 // İzin henüz sorulmadı — sadece gerekli features çalışır
17 enableBasicFunctionality()
18 @unknown default:
19 enableBasicFunctionality()
20 }
21}

SDK Manifest Composition

Bir uygulama, kullandığı tüm SDK'ların manifest'lerini otomatik merge eder. Ancak bazı durumlarda manuel müdahale gerekir.

Otomatik composition (Xcode 15+):

Xcode, app archive oluştururken tüm dependency'lerin PrivacyInfo.xcprivacy dosyalarını toplar ve app'in privacy report'unu oluşturur. Product → Generate Privacy Report ile kontrol edebilirsin.

swift
1// Privacy Report örneği (Xcode menüsünden):
2MyApp Privacy Report
3├── MyApp(App)
4│ └── NSPrivacyAccessedAPITypes: UserDefaults(CA92.1)
5├── Alamofire(Framework)
6│ └── NSPrivacyAccessedAPITypes: SystemBootTime(35F9.1)
7├── Firebase Analytics(Framework)
8│ ├── NSPrivacyTracking: true
9│ ├── NSPrivacyTrackingDomains: [app-measurement.com, ...]
10│ └── NSPrivacyAccessedAPITypes: UserDefaults, FileTimestamp, SystemBootTime
11└── SnapKit(Framework)
12 └── (No privacy manifest — WARNING!)

Manifest olmayan SDK için ne yaparsın?

swift
1// Eğer third-party SDK manifest içermiyorsa:
2// 1. Vendor'a issue aç (GitHub)
3// 2. Geçici olarak app'in manifest'ine SDK'nın kullandığı API'ları ekle
4// 3. App Review için "SDK manifest bekleniyoruz" notunu Review Notes'a ekle
5 
6// App'in PrivacyInfo.xcprivacy'ye SDK adına ek:
7// Bu doğru yaklaşım DEĞİL ama App Review geçiş için geçici

SPM ile manifest:

swift
1// Package.swift — SDK geliştiriyorsan
2let package = Package(
3 name: "MyAnalyticsSDK",
4 products: [...],
5 targets: [
6 .target(
7 name: "MyAnalyticsSDK",
8 resources: [
9 // PrivacyInfo.xcprivacy dosyasını bundle'a ekle
10 .process("Resources/PrivacyInfo.xcprivacy")
11 ]
12 )
13 ]
14)

Third-Party Binary Validation

2026'da App Store Connect, binary statik analizi ile manifest beyannamesini çapraz kontrol ediyor. Bu, önceden görülmemiş bir katmandır.

Nasıl çalışır?

  1. Submit edilmiş IPA içindeki tüm binary'ler (app + framework'ler) taranır
  2. Required Reason API çağrıları tespit edilir
  3. PrivacyInfo.xcprivacy ile karşılaştırılır
  4. Eşleşmeyen API'lar için otomatik warning veya rejection gelir

Lokal kontrol (CI/CD için):

bash
1# Xcode 15.3+ ile gelen privacy manifest validator
2xcrun privacy-manifest verify --app MyApp.ipa --manifest MyApp/PrivacyInfo.xcprivacy
3 
4# Çıktı örneği:
5# WARNING: NSPrivacyAccessedAPICategorySystemBootTime
6# Used in: Frameworks/ThirdPartySDK.framework
7# Not declared in manifest
8#
9# PASS: NSPrivacyAccessedAPICategoryUserDefaults
10# Declared reason: CA92.1
11# Found usage in: MyApp binary

GitHub Actions CI entegrasyonu:

yaml
1# .github/workflows/privacy-check.yml
2name: Privacy Manifest Check
3on: [pull_request]
4 
5jobs:
6 privacy-check:
7 runs-on: macos-15
8 steps:
9 - uses: actions/checkout@v4
10 - name: Build Archive
11 run: |
12 xcodebuild archive -scheme MyApp -destination "generic/platform=iOS" -archivePath build/MyApp.xcarchive
13 - name: Verify Privacy Manifest
14 run: |
15 xcrun privacy-manifest verify --archive build/MyApp.xcarchive || exit 1

ATT UX Best Practices

App Tracking Transparency popup'ının zamanlaması ve UX'i, opt-in oranını dramatik etkiler. Yanlış zamanlama %20-30'lara düşen opt-in anlamına gelir. Doğru yapıldığında %60-70'e çıkabilir.

Temel kural: Önce değer sun, sonra izin iste.

swift
1import AppTrackingTransparency
2import AdSupport
3 
4class TrackingManager {
5 // Singleton pattern
6 static let shared = TrackingManager()
7 private init() {}
8 
9 // ATT dialog'u zamanlama ile göster
10 func requestTrackingIfNeeded() async {
11 // İzin durumunu kontrol et
12 guard ATTrackingManager.trackingAuthorizationStatus == .notDetermined else {
13 return
14 }
15 
16 // Onboarding tamamlandıktan SONRA, belirli bir delay ile
17 // Kullanıcı uygulamayı deneyimledi — şimdi istemek daha mantıklı
18 try? await Task.sleep(nanoseconds: 1_000_000_000) // 1 saniye delay
19 
20 let status = await ATTrackingManager.requestTrackingAuthorization()
21 handleTrackingStatus(status)
22 }
23 
24 private func handleTrackingStatus(_ status: ATTrackingManager.AuthorizationStatus) {
25 switch status {
26 case .authorized:
27 // IDFA kullanılabilir
28 let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
29 AnalyticsManager.shared.configure(idfa: idfa)
30 case .denied, .restricted:
31 // Privacy-safe analytics: aggregated, non-identified
32 AnalyticsManager.shared.configurePrivacyMode()
33 case .notDetermined:
34 break
35 @unknown default:
36 break
37 }
38 }
39}

Pre-permission screen (custom dialog önce):

swift
1// Önce kendi açıklama ekranını göster, sonra system dialog'u aç
2struct TrackingPermissionView: View {
3 @Binding var isPresented: Bool
4 var onContinue: () -> Void
5 
6 var body: some View {
7 VStack(spacing: 24) {
8 Image(systemName: "chart.bar.xaxis")
9 .font(.system(size: 60))
10 .foregroundStyle(.blue)
11 
12 Text("Sana Daha İyi Deneyim Sunmak İstiyoruz")
13 .font(.title2.bold())
14 .multilineTextAlignment(.center)
15 
16 Text("Reklam performansını ölçmek için cihaz verisi kullanıyoruz. Bu sayede sana alakalı teklifler gösterebiliyoruz.")
17 .foregroundStyle(.secondary)
18 .multilineTextAlignment(.center)
19 
20 Button("Devam Et") {
21 isPresented = false
22 onContinue()
23 }
24 .buttonStyle(.borderedProminent)
25 
26 Button("Şimdi Değil") {
27 isPresented = false
28 // Tracking isteği yapma — kullanıcı red edecek
29 AnalyticsManager.shared.configurePrivacyMode()
30 }
31 .foregroundStyle(.secondary)
32 }
33 .padding(32)
34 }
35}

Ne zaman ATT istememeli?

  • Uygulama ilk açıldığında (onboarding tamamlanmadan önce)
  • Kullanıcı bir işlem yaparken (satın alma, kritik action)
  • Push notification izni ile aynı anda (çoklu permission fatigue)
  • Cold launch'da hemen

Ne zaman istenmeli?

  • Onboarding tamamlandıktan sonra
  • Kullanıcı uygulamanın değerini gördükten sonra (2-3. session)
  • Belirli bir feature'a girerken (reklamlı içerik bölümü)
  • Açıkça context sağlandıktan sonra

GDPR + CCPA + PDPL (Türkiye) + LGPD (Brezilya) gereklilikleri nedeniyle büyük uygulamalar Consent Management Platform (CMP) kullanıyor.

Popüler CMP'ler 2026:

Platform
iOS SDK
IAB TCF
Fiyat
OneTrust
Evet
v2.2
Kurumsal
Usercentrics
Evet
v2.2
€39/ay'dan
Didomi
Evet
v2.2
€99/ay'dan
Apple native
Partial
Hayır
Ücretsiz
swift
1// Usercentrics örneği (IAB TCF v2.2 uyumlu)
2import Usercentrics
3 
4class ConsentManager {
5 static func initialize() {
6 UsercentricsCore.configure(
7 options: UsercentricsOptions(settingsId: "YOUR_SETTINGS_ID")
8 )
9 }
10 
11 static func showConsentBanner(from viewController: UIViewController) async -> ConsentResult {
12 return await withCheckedContinuation { continuation in
13 let banner = UsercentricsBanner()
14 banner.showFirstLayer(hostView: viewController) { userResponse in
15 continuation.resume(returning: ConsentResult(
16 analytics: userResponse.consents["ga4"]?.status ?? false,
17 advertising: userResponse.consents["meta_pixel"]?.status ?? false
18 ))
19 }
20 }
21 }
22}
23 
24struct ConsentResult {
25 let analytics: Bool
26 let advertising: Bool
27}

Önemli: CMP kullansan bile iOS-native ATT dialog'u şart. CMP, GDPR/CCPA consent'ini yönetir; ATT, iOS platform-level tracking kontrolü. İkisi birbirini tamamlar, biri diğerinin yerini almaz.


IDFA Alternatifleri 2026

ATT ile IDFA erişimi kısıtlandıktan bu yana industry attribution ve analytics için alternatifler geliştirdi.

1. SKAdNetwork (Apple's solution):

swift
1import StoreKit
2 
3// SKAdNetwork 4.0 — attribution without user identification
4class AttributionManager {
5 static func updateConversionValue(_ value: Int) {
6 // 0-63 arası conversion value
7 // Apple aggregated olarak advertiser'a iletir
8 SKAdNetwork.updatePostbackConversionValue(
9 value,
10 coarseValue: .high, // SKAdNetwork 4.0 yeni
11 lockWindow: false
12 ) { error in
13 if let error = error {
14 print("SKAdNetwork error: \(error)")
15 }
16 }
17 }
18}
19 
20// Conversion value semantics — örnek mapping
21// 0: install
22// 1-10: engagement level
23// 11-20: purchase tier
24// 21-30: retention bucket

2. Meta Advanced Matching:

swift
1// IDFA olmadan hashed user data ile matching
2// E-posta/telefon SHA-256 hash ile gönderilir
3MetaAdvancedMatchingManager.configure(
4 email: "sha256_hash_of_email",
5 phone: "sha256_hash_of_phone"
6)
7// Meta, kendi user database ile match eder

3. AppsFlyer SKAN + Probabilistic:

swift
1// ATT kabul edenler için IDFA
2// Reddedenlere probabilistic modeling (IP + device signals)
3// IDFA erişimi yokken fingerprinting yasaklı — sadece SKAdNetwork

4. Privacy-preserving analytics:

swift
1// Mixpanel Identity Merge — server-side, non-identifying
2// PostHog — open source, self-hosted option
3// Amplitude — cohort analytics without user-level tracking
4 
5// Genel yaklaşım: session-level, aggregate, no persistent ID
6class PrivacyAnalytics {
7 // Session ID: app open'da random UUID, kapanınca sil
8 private let sessionID = UUID().uuidString
9 
10 func trackEvent(_ name: String, properties: [String: Any] = [:]) {
11 var enrichedProps = properties
12 enrichedProps["session_id"] = sessionID
13 enrichedProps["app_version"] = Bundle.main.appVersion
14 // User-specific ID yok — session bazlı aggregate
15 sendToBackend(event: name, properties: enrichedProps)
16 }
17}

2026 App Store Rejection Sebepleri

Gerçek App Review rejection deneyimlerinden derlenen 2026 güncel liste:

Privacy Manifest ile ilgili rejectionlar:

swift
1Rejection 1:
2"ITMS-91053: Missing API declaration"
3Sebep: NSUserDefaults API kullanıldı, manifest'te declare edilmedi
4Çözüm: PrivacyInfo.xcprivacy'e CA92.1 reason ekle
5 
6Rejection 2:
7"ITMS-91055: Invalid privacy manifest"
8Sebep: NSPrivacyAccessedAPITypeReasons array boş bırakıldı
9Çözüm: Geçerli reason kodu ekle(boş array kabul edilmiyor)
10 
11Rejection 3:
12"ITMS-91056: Privacy manifest in dependency"
13Sebep: Third-party SDK(örn. eskiFirebase sürümü) manifest içermiyor
14Çözüm: SDK'yı güncelle veya App Review Notes'a açıklama ekle
15 
16Rejection 4:
17"ITMS-91057: NSPrivacyTracking inconsistency"
18Sebep: NSPrivacyTracking = false ama tracking domain'ler var
19Çözüm: NSPrivacyTracking = true yap veya domain'leri kaldır
20 
21Rejection 5:
22"5.1.1 Data Collection and Storage"
23Sebep: Kullanıcı onayı olmadan kişisel veri toplandı
24Çözüm: Consent flow ekle, privacy policy güncelle

ATT ile ilgili rejectionlar:

swift
1Rejection 6:
2"5.1.2 Data Use and Sharing"
3Sebep: ATT izni olmadan kullanıcı track ediliyor
4Çözüm: ATTrackingManager.requestTrackingAuthorization() ekle
5 
6Rejection 7:
7"2.5.4 Software Requirements"
8Sebep: ATT dialog öncesi "izin ver"in baskı yapan custom UI
9Çözüm: Pre-permission screen tarafsız olmalı — "izin ver"in teşvik YASAK

Önlem stratejisi:

swift
1// Pre-submission checklist
2// 1. xcrun privacy-manifest verify — lokal kontrol
3// 2. Xcode "Generate Privacy Report" — tüm dependency'ler
4// 3. ATT flow test: denied + authorized + not determined
5// 4. Tracking domain DNS check — hangi domain'ler gerçekten kullanılıyor?
6// 5. Privacy Nutrition Label'ı App Store Connect'te manuel review

Compliance Checklist

2026 App Store submission için tam compliance checklist:

PrivacyInfo.xcprivacy:

  • Dosya var ve doğru target'a üye
  • NSPrivacyTracking doğru set (true/false)
  • NSPrivacyTrackingDomains — tracking = true ise dolu, false ise boş
  • NSPrivacyAccessedAPITypes — kullanılan her Required Reason API declare edildi
  • Her API için geçerli reason kodu var (boş array yok)
  • NSPrivacyCollectedDataTypes — gerçek veri toplama ile eşleşiyor

SDK Dependency'leri:

  • Tüm SPM/CocoaPods/XCFramework manifest'leri var
  • `xcrun privacy-manifest verify` clean geçti
  • Firebase, Analytics SDK'lar güncel sürümde

ATT Implementation:

  • `ATTrackingManager.requestTrackingAuthorization()` implemente
  • Info.plist'te `NSUserTrackingUsageDescription` var
  • ATT öncesi pre-permission screen tarafsız (baskı yok)
  • Denied durumunda graceful degradation çalışıyor
  • Tracking domain'ler ATT denied'da engelleniyor (test edildi)

Privacy Policy:

  • Privacy policy URL App Store Connect'te kayıtlı
  • Toplanan veriler privacy policy ile eşleşiyor
  • GDPR/CCPA/PDPL uyumlu bölümler var

App Store Connect:

  • Privacy Nutrition Label dolduruldu
  • "App Collects Data" beyanı gerçekle eşleşiyor
  • Data linked to identity doğru işaretlendi

bash
1#!/bin/bash
2# privacy-audit.sh — Her PR'da otomatik çalıştır
3 
4echo "Checking Privacy Manifests for all dependencies..."
5 
6# SPM cache'inden tüm PrivacyInfo.xcprivacy dosyalarını bul
7MANIFESTS=$(find ~/Library/Developer/Xcode/DerivedData -name "PrivacyInfo.xcprivacy" 2>/dev/null)
8PACKAGE_DIRS=$(find .build -name "*.xcprivacy" 2>/dev/null)
9 
10# Manifest olmayan framework'leri tespit et
11find . -name "*.xcframework" -o -name "*.framework" | while read framework; do
12 if [ ! -f "$framework/PrivacyInfo.xcprivacy" ]; then
13 echo "WARNING: No privacy manifest in $framework"
14 fi
15done
16 
17echo "Run 'xcrun privacy-manifest verify' for detailed analysis"

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

swift
1class ATTTimingManager {
2 private static let sessionCountKey = "att_session_count"
3 private static let hasRequestedKey = "att_has_requested"
4 
5 static func shouldRequestTracking() -> Bool {
6 guard !UserDefaults.standard.bool(forKey: hasRequestedKey) else {
7 return false // Zaten soruldu
8 }
9 
10 let count = UserDefaults.standard.integer(forKey: sessionCountKey)
11 return count >= 2 // 3. session'dan itibaren sor
12 }
13 
14 static func incrementSessionCount() {
15 let current = UserDefaults.standard.integer(forKey: sessionCountKey)
16 UserDefaults.standard.set(current + 1, forKey: sessionCountKey)
17 }
18 
19 static func markAsRequested() {
20 UserDefaults.standard.set(true, forKey: hasRequestedKey)
21 }
22}
23 
24// AppDelegate veya SceneDelegate'de:
25func sceneDidBecomeActive(_ scene: UIScene) {
26 ATTTimingManager.incrementSessionCount()
27 
28 if ATTTimingManager.shouldRequestTracking() {
29 Task {
30 await TrackingManager.shared.requestTrackingIfNeeded()
31 ATTTimingManager.markAsRequested()
32 }
33 }
34}

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?

Okuyucu Ödülü

**iOS 19 Privacy Layer (Beta, 2026):** iOS 19 beta'da görülen yeni privacy özelliği — "Privacy Dashboard" ekranında kullanıcılar hangi app'in hangi API'yı ne zaman kullandığını görebilecek. Bu aşamada geliştirici için değişiklik gerektirmiyor ama şunu işaret ediyor: Privacy Manifest'teki her beyannamen kullanıcı tarafından görülebilir hale geliyor. Pratik öneri: Manifest'ini aggressive tut — sadece gerçekten kullandığın API'ları declare et. "Gelecekte lazım olabilir" diye ekstra reason declare etme. Her beyannamen audit trail oluşturuyor. **Fingerprinting detection (iOS 19 yeni):** iOS 19 ile Apple, bilinen fingerprinting pattern'lerini runtime'da tespit eden bir sistem sunuyor. `ct_syscall`, `getsockopt` ve benzeri low-level API kombinasyonları monitör ediliyor. Bu API'ları kullanan SDK'lar (eski sürüm bazı analytics SDK'lar) runtime'da kısıtlama alabilir — manifest'e ne yazarsan yaz. Fingerprinting şüphesi taşıyan API kombinasyonları: - `mach_absolute_time()` + `sysctlbyname("hw.machine")` + `UIDevice.model` - `UIScreen.main.scale` + `ProcessInfo.systemUptime` + disk info Bu kombinasyonları kullanan third-party library kullanıyorsan şimdi güncelle veya çıkar.

Sonuç

iOS Privacy Manifests, sadece compliance checkbox doldurmak değil — kullanıcıya ve App Store review ekibine şeffaf bir sözleşme sunmak. 2026'da bu sözleşmenin detayları her zamankinden daha fazla denetleniyor: binary analizi, SDK manifest kontrolü, ATT flow review.

Doğru yaklaşım: Privacy-by-design. Baştan toplanacak veriyi minimize et, her toplanan veri için açık reason belirle, ATT flow'unu kullanıcı deneyimine zarar vermeden uygula. Bu yaklaşım hem App Store rejection'ı önler hem de kullanıcı güvenini artırır — ve araştırmalar güvenilir bulunan uygulamaların retention'ının %23 daha yüksek olduğunu gösteriyor.

İlgili Kaynaklar:

Sonraki adım: StoreKit 2 Production Subscription Guide ve iOS Privacy Compliance ATT yazılarını incele.

Etiketler

#Privacy#App Tracking#ATT#Privacy Manifest#iOS#Compliance#App Store#2026
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz