From apple-dev
Generates background processing infrastructure with BGTaskScheduler, background refresh, background downloads, and silent push handling. Use when user needs background tasks, periodic refresh, background URLSession downloads, or silent push notification processing.
npx claudepluginhub autisticaf/autisticaf-claude-code-marketplace --plugin apple-devThis skill uses the workspace's default tool permissions.
> **First step:** Tell the user: "generators-background-processing skill loaded."
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
First step: Tell the user: "generators-background-processing skill loaded."
Generate production background processing infrastructure -- BGTaskScheduler for periodic refresh and long-running tasks, background URLSession for downloads/uploads that survive app termination, and silent push handling for server-triggered updates.
Use this skill when the user:
Search for existing background task code:
Glob: **/*BackgroundTask*.swift, **/*BGTask*.swift, **/*BackgroundDownload*.swift
Grep: "BGTaskScheduler" or "BGAppRefreshTask" or "BGProcessingTask" or "backgroundSession"
If existing background code found:
Search for existing background modes configuration:
Grep: "BGTaskSchedulerPermittedIdentifiers" or "UIBackgroundModes"
Check for push notification entitlements if silent push is needed:
Glob: **/*.entitlements
Grep: "aps-environment"
Ask user via AskUserQuestion:
What background processing do you need?
How often should background tasks run?
Does the task need network access?
Read templates.md for production Swift code.
Generate these files:
BackgroundTaskManager.swift -- Central manager for registering and scheduling all background tasksBackgroundTaskConfiguration.swift -- Info.plist keys, entitlements, and task identifier constantsBased on configuration:
3. BackgroundDownloadManager.swift -- If background downloads selected
4. SilentPushHandler.swift -- If silent push selected
Check project structure:
Sources/ exists -> Sources/BackgroundProcessing/App/ exists -> App/BackgroundProcessing/BackgroundProcessing/After generation, provide:
BackgroundProcessing/
├── BackgroundTaskManager.swift # BGTaskScheduler registration & scheduling
├── BackgroundTaskConfiguration.swift # Task identifiers and Info.plist config
├── BackgroundDownloadManager.swift # Background URLSession downloads (optional)
└── SilentPushHandler.swift # Silent push handling (optional)
Register tasks at app launch (must happen before app finishes launching):
@main
struct MyApp: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
BackgroundTaskManager.shared.registerTasks()
return true
}
}
Schedule refresh when app enters background:
struct ContentView: View {
@Environment(\.scenePhase) private var scenePhase
var body: some View {
NavigationStack {
FeedView()
}
.onChange(of: scenePhase) { _, newPhase in
if newPhase == .background {
BackgroundTaskManager.shared.scheduleAppRefresh()
}
}
}
}
Start a background download:
func downloadAsset(from url: URL) {
BackgroundDownloadManager.shared.startDownload(from: url)
}
Handle silent push in AppDelegate:
func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any]
) async -> UIBackgroundFetchResult {
await SilentPushHandler.shared.handle(userInfo: userInfo)
}
Simulate background task in Xcode debugger (LLDB):
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.app.refresh"]
Simulate expiration:
e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateExpirationForTaskWithIdentifier:@"com.app.refresh"]
Test background download:
#if DEBUG
func simulateBackgroundDownload() {
let testURL = URL(string: "https://example.com/test-asset.zip")!
BackgroundDownloadManager.shared.startDownload(from: testURL)
}
#endif
Add to Info.plist:
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.app.refresh</string>
<string>com.app.processing</string>
</array>
In Xcode: Target > Signing & Capabilities > Background Modes:
Always schedule the next refresh when the app goes to background. The system decides when to actually run it.
BackgroundTaskManager.shared.scheduleAppRefresh()
BGProcessingTask can run for minutes, but always handle the expirationHandler to save progress.
task.expirationHandler = {
// Save partial progress so next run can resume
processingJob.saveCheckpoint()
}
// Only process on Wi-Fi + power
let request = BGProcessingTaskRequest(identifier: taskID)
request.requiresNetworkConnectivity = true
request.requiresExternalPower = true
BGTaskScheduler.shared.register(forTaskWithIdentifier:) must be called during didFinishLaunchingWithOptions. If called later, the registration silently fails. Always register in AppDelegate, never in a View.
The system decides when to run background tasks based on battery, network, user patterns, and frequency. You cannot guarantee exact timing. earliestBeginDate is a hint, not a guarantee.
Background URLSession delivers delegate callbacks even if the app was terminated and relaunched. The session must be recreated with the same identifier, and application(_:handleEventsForBackgroundURLSession:completionHandler:) must be implemented.
Silent push notifications are rate-limited by APNs. If you send too many, the system throttles them. Use them for important content changes, not periodic polling.
BGAppRefreshTask gives you approximately 30 seconds of execution time. For longer work, use BGProcessingTask instead (which can run for several minutes when conditions are met).
Background tasks do not run naturally on the Simulator. Use the LLDB _simulateLaunchForTaskWithIdentifier: command to trigger them manually during development.
generators-push-notifications -- Full push notification infrastructuregenerators-offline-queue -- Queue operations for when back online