---
name: cocoapods-privacy-manifests
user-invocable: false
description: Use when implementing iOS 17+ privacy manifests for CocoaPods libraries. Covers PrivacyInfo.xcprivacy file creation, required reasons API declarations, and proper resource bundle integration for App Store compliance.
allowed-tools:
- Read
- Write
- Edit
- Bash
- Grep
- Glob
---
# CocoaPods - Privacy Manifests
Implement iOS 17+ privacy manifests for App Store compliance and user transparency.
## What Are Privacy Manifests?
Privacy manifests (`PrivacyInfo.xcprivacy`) are XML property list files that declare:
- Data collection and usage practices
- Required Reasons API usage
- Tracking domains
- Privacy-sensitive APIs
### Why Privacy Manifests?
Starting with iOS 17 and Xcode 15, Apple requires privacy manifests for:
- Apps using privacy-sensitive APIs
- Third-party SDKs and frameworks
- Any code accessing user data
## Privacy Manifest File Format
### Basic Structure
```xml
NSPrivacyTracking
NSPrivacyTrackingDomains
NSPrivacyCollectedDataTypes
NSPrivacyAccessedAPITypes
```
## Including in Podspec
### Resource Bundle (Recommended)
```ruby
Pod::Spec.new do |spec|
spec.name = 'MyLibrary'
spec.version = '1.0.0'
spec.source_files = 'Source/**/*.swift'
# Include privacy manifest in resource bundle
spec.resource_bundles = {
'MyLibrary' => [
'Resources/**/*.xcprivacy',
'Resources/**/*.{png,jpg,xcassets}'
]
}
end
```
### Direct Resources (Alternative)
```ruby
spec.resources = 'Resources/PrivacyInfo.xcprivacy'
# Or with glob pattern
spec.resources = 'Resources/**/*.xcprivacy'
```
### File Location
```
MyLibrary/
├── MyLibrary.podspec
├── Source/
│ └── MyLibrary/
└── Resources/
├── PrivacyInfo.xcprivacy # Privacy manifest
└── Assets.xcassets
```
## Required Reasons APIs
### Common APIs Requiring Reasons
Apple requires declarations for these privacy-sensitive APIs:
#### File Timestamp APIs
```xml
NSPrivacyAccessedAPITypes
NSPrivacyAccessedAPIType
NSPrivacyAccessedAPICategoryFileTimestamp
NSPrivacyAccessedAPITypeReasons
C617.1
```
**Reason Codes:**
- `C617.1`: Display timestamps to user
- `0A2A.1`: Access timestamps of files in app container
- `3B52.1`: Access timestamps for app functionality
- `DDA9.1`: Timestamp access for debugging
#### User Defaults APIs
```xml
NSPrivacyAccessedAPIType
NSPrivacyAccessedAPICategoryUserDefaults
NSPrivacyAccessedAPITypeReasons
CA92.1
```
**Reason Codes:**
- `CA92.1`: Access user defaults in same app group
- `1C8F.1`: Access user defaults for app functionality
- `C56D.1`: SDK-specific configuration preferences
- `AC6B.1`: Third-party SDK functionality
#### System Boot Time APIs
```xml
NSPrivacyAccessedAPIType
NSPrivacyAccessedAPICategorySystemBootTime
NSPrivacyAccessedAPITypeReasons
35F9.1
```
**Reason Codes:**
- `35F9.1`: Measure time elapsed for app functionality
- `8FFB.1`: Calculate absolute timestamp
- `3D61.1`: Measure time for performance testing
#### Disk Space APIs
```xml
NSPrivacyAccessedAPIType
NSPrivacyAccessedAPICategoryDiskSpace
NSPrivacyAccessedAPITypeReasons
85F4.1
```
**Reason Codes:**
- `85F4.1`: Display disk space to user
- `E174.1`: Check disk space before file operations
- `7D9E.1`: Health/fitness app disk space
- `B728.1`: User-initiated file management
## Data Collection
### Declaring Collected Data
```xml
NSPrivacyCollectedDataTypes
NSPrivacyCollectedDataType
NSPrivacyCollectedDataTypeEmailAddress
NSPrivacyCollectedDataTypeLinked
NSPrivacyCollectedDataTypeTracking
NSPrivacyCollectedDataTypePurposes
NSPrivacyCollectedDataTypePurposeAppFunctionality
```
### Common Data Types
- `NSPrivacyCollectedDataTypeEmailAddress`
- `NSPrivacyCollectedDataTypeName`
- `NSPrivacyCollectedDataTypePhoneNumber`
- `NSPrivacyCollectedDataTypeDeviceID`
- `NSPrivacyCollectedDataTypeUserID`
- `NSPrivacyCollectedDataTypePreciseLocation`
- `NSPrivacyCollectedDataTypeCoarseLocation`
- `NSPrivacyCollectedDataTypeSearchHistory`
- `NSPrivacyCollectedDataTypeBrowsingHistory`
### Collection Purposes
- `NSPrivacyCollectedDataTypePurposeThirdPartyAdvertising`
- `NSPrivacyCollectedDataTypePurposeAppFunctionality`
- `NSPrivacyCollectedDataTypePurposeAnalytics`
- `NSPrivacyCollectedDataTypePurposeProductPersonalization`
- `NSPrivacyCollectedDataTypePurposeOther`
## Tracking Configuration
### No Tracking
```xml
NSPrivacyTracking
NSPrivacyTrackingDomains
```
### With Tracking
```xml
NSPrivacyTracking
NSPrivacyTrackingDomains
analytics.example.com
tracking.example.com
```
## Complete Example
### Networking SDK Privacy Manifest
```xml
NSPrivacyTracking
NSPrivacyTrackingDomains
NSPrivacyCollectedDataTypes
NSPrivacyCollectedDataType
NSPrivacyCollectedDataTypeUserID
NSPrivacyCollectedDataTypeLinked
NSPrivacyCollectedDataTypeTracking
NSPrivacyCollectedDataTypePurposes
NSPrivacyCollectedDataTypePurposeAppFunctionality
NSPrivacyAccessedAPITypes
NSPrivacyAccessedAPIType
NSPrivacyAccessedAPICategoryUserDefaults
NSPrivacyAccessedAPITypeReasons
CA92.1
NSPrivacyAccessedAPIType
NSPrivacyAccessedAPICategoryFileTimestamp
NSPrivacyAccessedAPITypeReasons
3B52.1
```
### Analytics SDK Privacy Manifest
```xml
NSPrivacyTracking
NSPrivacyTrackingDomains
analytics.myservice.com
NSPrivacyCollectedDataTypes
NSPrivacyCollectedDataType
NSPrivacyCollectedDataTypeDeviceID
NSPrivacyCollectedDataTypeLinked
NSPrivacyCollectedDataTypeTracking
NSPrivacyCollectedDataTypePurposes
NSPrivacyCollectedDataTypePurposeAnalytics
NSPrivacyAccessedAPITypes
NSPrivacyAccessedAPIType
NSPrivacyAccessedAPICategorySystemBootTime
NSPrivacyAccessedAPITypeReasons
35F9.1
```
## CocoaPods Integration
### Podspec Configuration
```ruby
Pod::Spec.new do |spec|
spec.name = 'MyAnalyticsSDK'
spec.version = '1.0.0'
spec.ios.deployment_target = '13.0'
spec.source_files = 'Source/**/*.swift'
# Include privacy manifest
spec.resource_bundles = {
'MyAnalyticsSDK' => [
'Resources/PrivacyInfo.xcprivacy'
]
}
# Platform-specific privacy manifests
spec.ios.resource_bundles = {
'MyAnalyticsSDK_iOS' => ['Resources/iOS/PrivacyInfo.xcprivacy']
}
spec.osx.resource_bundles = {
'MyAnalyticsSDK_macOS' => ['Resources/macOS/PrivacyInfo.xcprivacy']
}
end
```
## Validation
### Check Privacy Manifest
```bash
# Lint with privacy manifest
pod lib lint
# Validate privacy manifest is included
pod lib lint --verbose | grep -i privacy
```
### Xcode Validation
1. Build your library in Xcode
2. Open **Report Navigator**
3. Check for privacy warnings
4. Verify privacy manifest in bundle
### App Store Validation
```bash
# Generate .xcarchive
xcodebuild archive -workspace MyApp.xcworkspace -scheme MyApp
# Validate before submission
xcodebuild -exportArchive -archivePath MyApp.xcarchive -exportPath MyApp.ipa -exportOptionsPlist ExportOptions.plist
```
## Best Practices
### Minimal Disclosure
```xml
NSPrivacyCollectedDataTypes
```
### Accurate Reasons
```xml
NSPrivacyAccessedAPITypeReasons
CA92.1
```
### Regular Updates
```ruby
# Update privacy manifest when adding new APIs
spec.version = '1.1.0' # Bump version
# Update PrivacyInfo.xcprivacy with new declarations
```
## Anti-Patterns
### Don't
❌ Omit privacy manifest for iOS 17+ apps
```ruby
# Missing privacy manifest - App Store rejection risk
spec.resource_bundles = {
'MyLibrary' => ['Resources/**/*.png']
# No PrivacyInfo.xcprivacy
}
```
❌ Use incorrect reason codes
```xml
WRONG.1
```
❌ Declare tracking without domains
```xml
NSPrivacyTracking
NSPrivacyTrackingDomains
```
### Do
✅ Include privacy manifest for all iOS SDKs
```ruby
spec.resource_bundles = {
'MyLibrary' => ['Resources/PrivacyInfo.xcprivacy']
}
```
✅ Use accurate reason codes
```xml
CA92.1
```
✅ Be truthful about tracking
```xml
NSPrivacyTracking
NSPrivacyTrackingDomains
analytics.example.com
```
## Resources
- [Apple Privacy Manifest Documentation](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files)
- [Required Reasons API Reference](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api)
- [App Privacy Details](https://developer.apple.com/app-store/app-privacy-details/)
## Related Skills
- cocoapods-podspec-fundamentals
- cocoapods-subspecs-organization
- cocoapods-publishing-workflow