[ad_1]
I am having problem attempting to determine the right way to use Background Duties appropriately in my SwiftUI challenge for iOS 15. For the reason that new SwiftUI lifecycle does not include an AppDelegate, I used my knowledge mannequin as an alternative for including background duties and set an surroundings object in App.
Every thing appears to work, background duties are being run however the subject I am having is my Printed variable solely appears to replace after I open the applying. I am undecided if that is even the proper method to fetch knowledge from an API within the background.
Here is a demo video since a gif would have been to giant to add. The difficulty appears to be the Pokémon does not appear to alter however solely when the applying has been launched after seeing there’s been a background process run. The tip purpose is to have my View replace with out having to open the applying earlier than I see any adjustments. I am nonetheless studying as I am going, any assist can be a lot appreciated.
Knowledge Mannequin
struct Pokemon: Codable {
let sprites: Sprites
let identify: String
enum CodingKeys: String, CodingKey {
case sprites
case identify
}
}
struct Sprites: Codable {
let frontDefault: String
enum CodingKeys: String, CodingKey {
case frontDefault = "front_default"
}
}
class DataModel: ObservableObject {
let taskIdentifier = "com.instance.take a look at.refresh"
non-public var cancellables = Set<AnyCancellable>()
@Printed var pokemon = Pokemon(sprites: Sprites(frontDefault: "", frontShiny: ""), identify: "", varieties: [])
func getpokemon() {
let request = URLRequest(url: URL(string: "https://pokeapi.co/api/v2/pokemon/(Int.random(in: 1..<450))")!)
URLSession.shared.dataTaskPublisher(for: request)
.map{ $0.knowledge }
.decode(kind: Pokemon.self, decoder: JSONDecoder())
.obtain(on: DispatchQueue.principal)
.sink(receiveCompletion: { print ("Obtained completion: ($0).") },
receiveValue: { pokemon in
self.pokemon = pokemon
})
.retailer(in: &cancellables)
}
func register() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, utilizing: nil) { process in
self.handleAppRefresh(process: process as! BGAppRefreshTask)
}
}
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: taskIdentifier)
request.earliestBeginDate = Date(timeIntervalSinceNow: 10 * 60)
do {
strive BGTaskScheduler.shared.submit(request)
} catch {
print("Couldn't schedule app refresh: (error)")
}
}
func handleAppRefresh(process: BGAppRefreshTask) {
scheduleAppRefresh()
process.expirationHandler = {
print("expired")
//process.setTaskCompleted(success: false)
}
self.getpokemon()
process.setTaskCompleted(success: true)
}
}
App
import SwiftUI
import BackgroundTasks
@principal
struct BackgroudTaskApp: App {
@ObservedObject var knowledge = DataModel()
init() {
knowledge.register()
knowledge.scheduleAppRefresh()
}
var physique: some Scene {
WindowGroup {
ContentView()
.environmentObject(knowledge)
.onAppear(carry out: knowledge.getpokemon)
}
}
}
SwiftUI View
struct ContentView: View {
@EnvironmentObject var knowledge: DataModel
var physique: some View {
Button(motion: {
withAnimation {
knowledge.getpokemon()
}
}, label: {
VStack(spacing: 0) {
AsyncImage(url:URL(string:knowledge.pokemon.sprites.frontDefault)) { picture in
picture
.resizable()
} placeholder: {
ProgressView()
}
.body(width: 120, top: 120)
}}
).buttonStyle(.plain)
}
}
[ad_2]
