SwiftUI: Scheduling Daily, Dynamic Notifications Fetched From API

3 min read 04-10-2024
SwiftUI: Scheduling Daily, Dynamic Notifications Fetched From API


SwiftUI: Scheduling Dynamic Notifications Fetched from an API

Notifications are a powerful way to keep your users engaged and informed about critical events in your app. But what if you need to schedule notifications based on data that changes regularly, perhaps coming from an external API? In this article, we'll dive into how you can achieve this in SwiftUI, empowering you to create dynamic and personalized notification experiences.

The Challenge

Imagine you have a fitness app where users can set daily workout goals. These goals could be fetched from a server, potentially changing each day based on user progress or personal factors. We want to notify users when their workout goal is ready, but the notification schedule needs to adjust based on this dynamic data.

Setting the Stage

Let's start with a simplified example using SwiftUI and UNUserNotificationCenter. We'll assume our workout goal data is fetched from an API endpoint:

import SwiftUI
import UserNotifications

struct ContentView: View {
    @State private var workoutGoal: String = ""
    
    var body: some View {
        VStack {
            Text("Today's Workout Goal: \(workoutGoal)")
            Button("Fetch Goal") {
                fetchWorkoutGoal()
            }
        }
        .onAppear {
            requestNotificationPermission()
        }
    }

    private func fetchWorkoutGoal() {
        // Replace this with your actual API call
        let sampleGoal = "Complete 30 minutes of cardio"
        workoutGoal = sampleGoal
        scheduleNotification(goal: sampleGoal)
    }
    
    private func requestNotificationPermission() {
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .sound]) { granted, error in
            // Handle permission result
        }
    }

    private func scheduleNotification(goal: String) {
        let content = UNMutableNotificationContent()
        content.title = "Workout Time!"
        content.body = "Your goal for today is: \(goal)"

        // Assuming the goal is ready at 6:00 AM
        let dateComponents = DateComponents(hour: 6, minute: 0)
        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)

        let request = UNNotificationRequest(identifier: "workoutNotification", content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request)
    }
}

This example shows how to request notification permission, fetch a sample workout goal, and schedule a daily notification at a fixed time.

Dynamic Scheduling

The core issue here is the fixed schedule. To make it dynamic, we need to fetch the workout goal data and use that data to schedule the notification. Here's how:

  1. Fetch Goal and Time: When fetching the goal from the API, also fetch the desired notification time.
  2. Construct Dynamic Trigger: Instead of using UNCalendarNotificationTrigger with a fixed time, utilize UNTimeIntervalNotificationTrigger which allows setting the notification delay based on the fetched time.
  3. Update Schedule: Upon receiving the data, update the existing notification (with the same identifier) or create a new one with the dynamic time.

Example Implementation:

// ... (previous code)

private func fetchWorkoutGoal() {
    // API call to fetch workout goal and notification time
    // ...

    // Assuming API returns data in a dictionary format:
    let goalData = ["goal": "Run 5 miles", "notificationTime": 18000] // 5 hours in seconds

    workoutGoal = goalData["goal"] as! String
    let notificationDelay = goalData["notificationTime"] as! Int

    scheduleNotification(goal: workoutGoal, delay: notificationDelay)
}

private func scheduleNotification(goal: String, delay: Int) {
    let content = UNMutableNotificationContent()
    content.title = "Workout Time!"
    content.body = "Your goal for today is: \(goal)"

    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: TimeInterval(delay), repeats: false) 
    
    let request = UNNotificationRequest(identifier: "workoutNotification", content: content, trigger: trigger)
    UNUserNotificationCenter.current().add(request)
}

// ... (rest of the code)

Key Considerations

  • API Design: Ensure your API returns the necessary data for dynamic scheduling, including notification time.
  • Notification Time Format: Make sure the notification time is in a format that can be easily converted to seconds.
  • Update Mechanism: Implement a mechanism to fetch and update the notification schedule periodically. You can use timer-based updates or background fetch.
  • User Preferences: Provide users with the option to customize notification settings and preferences.

Advanced Techniques

  • Geolocation: Use geolocation data to trigger notifications when users are near specific locations relevant to their workouts.
  • Local Notifications: For immediate notifications, consider utilizing local notifications, which bypass the need for an API fetch.
  • User Interface: Implement clear visual feedback to users about scheduled notifications and their ability to manage them.

Conclusion

By leveraging SwiftUI's capabilities and effectively integrating with APIs, you can create dynamic and personalized notification experiences. This allows for greater engagement and empowers your users to stay on track with their goals. Remember to prioritize user experience, providing clear control and settings for their notifications.