Post

Replies

Boosts

Views

Activity

watchOS SwiftUI background task not working
I'm attempting to create a standalone watchOS app that fetches the prayer timings of my local mosque in JSON format via an API call. I want the app to fetch the prayer timings in the background, but only once per day, at the start of the day (when prayer timings change, i.e., midnight). I'm trying to implement this using SwiftUI's backgroundTask modifier as explained in the docs and in this WWDC22 video. I made sure to enable the Background Modes capability, and this is what my app's Info.plist looks like: However, I've been unable to get it to work. I would appreciate any assistance I can get and feedback for improvements I can make, even with the Info.plist if anything is incorrect about it. Thank you! This is what I have so far: // PrayerTimesCompanionApp.swift // PrayerTimesCompanion Watch App import SwiftUI import WatchKit @main struct PrayerTimesCompanion_Watch_AppApp: App { var body: some Scene { WindowGroup { ContentView() } .backgroundTask(.appRefresh("TIMINGS_REFRESH")) { print("Found matching task") scheduleNextBackgroundRefresh() } } } // Schedule the next background refresh func scheduleNextBackgroundRefresh() { let today = Calendar.current.startOfDay(for: .now) if let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: today) { WKApplication.shared().scheduleBackgroundRefresh(withPreferredDate: tomorrow, userInfo: "TIMINGS_REFRESH" as NSSecureCoding & NSObjectProtocol) { error in if error != nil { fatalError("*** An error occurred while scheduling the background refresh task. ***") } print("*** Scheduled! ***") } } } // ContentView.swift // PrayerTimesCompanion Watch App import SwiftUI struct ContentView: View { @StateObject var prayerTimeModel = PrayerTimesModel() var body: some View { List { VStack { VStack(spacing: 15) { // Table Header HStack { Text("Prayer") .bold() .frame(maxWidth: .infinity, alignment: .leading) // Align to the left Text("Iqamah") .bold() .frame(maxWidth: .infinity, alignment: .trailing) // Align to the right } .padding() // Table Rows (5 prayers) ForEach(prayerTimeModel.prayerTimes.data.iqamah, id: \.date) { iqamah in rowView(prayer: "Fajr", time: iqamah.fajr) rowView(prayer: "Zuhr", time: iqamah.zuhr) rowView(prayer: "Asr", time: iqamah.asr) rowView(prayer: "Maghrib", time: iqamah.maghrib) rowView(prayer: "Isha", time: iqamah.isha) } } .padding() } .padding() .onAppear { prayerTimeModel.fetch() } } .edgesIgnoringSafeArea(.top) } func rowView(prayer: String, time: String) -> some View { HStack { Text(prayer) .frame(maxWidth: .infinity, alignment: .leading) Text(time) .frame(maxWidth: .infinity, alignment: .trailing) } } } #Preview { ContentView() } // PrayerTimesModel.swift // PrayerTimesCompanion Watch App import Foundation import SwiftUI // Main struct for the response struct PrayerTimesResponse: Codable { let status: String var data: SalahData let message: [String] } // Struct for the data section struct SalahData: Codable { var salah: [Salah] var iqamah: [Iqamah] } // Struct for Salah times struct Salah: Codable { let date: String let hijriDate: String let hijriMonth: String let day: String var fajr: String let sunrise: String var zuhr: String var asr: String var maghrib: String var isha: String enum CodingKeys: String, CodingKey { case date, hijriDate = "hijri_date", hijriMonth = "hijri_month", day, fajr, sunrise, zuhr, asr, maghrib, isha } } // Struct for Iqamah times struct Iqamah: Codable { let date: String var fajr: String var zuhr: String var asr: String var maghrib: String var isha: String let jummah1: String let jummah2: String enum CodingKeys: String, CodingKey { case date, fajr, zuhr, asr, maghrib, isha, jummah1 = "jummah1", jummah2 = "jummah2" } } class PrayerTimesModel: ObservableObject { @Published var prayerTimes: PrayerTimesResponse = PrayerTimesResponse( status: "Unknown", data: SalahData( salah: [Salah(date: "", hijriDate: "", hijriMonth: "", day: "", fajr: "", sunrise: "", zuhr: "", asr: "", maghrib: "", isha: "")], iqamah: [Iqamah(date: "", fajr: "", zuhr: "", asr: "", maghrib: "", isha: "", jummah1: "", jummah2: "")]), message: ["No data available"] ) // fetches the local mosque's prayer timings via an API call func fetch() { guard let url = URL(string: "https://masjidal.com/api/v1/time/range?masjid_id=3OA87VLp") else { return } let task = URLSession.shared.dataTask(with: url) { [self] data, _, error in guard let data = data, error == nil else { return } // Convert to JSON do { var prayerTimes = try JSONDecoder().decode(PrayerTimesResponse.self, from: data) DispatchQueue.main.async { self.prayerTimes = prayerTimes } } catch { print(error) } } task.resume() } }
0
0
351
Sep ’24