Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
For some reason, the line with the print statement skips when stepping through code despite having a breakpoint:
var body: some View {
Text("Test")
.onAppear {
print("test")
}
}
With my implementation, I am just using SubscriptionStoreView() so I wasn't able to apply the link you shared. I tried something like this:
.onChange(of: Product.PurchaseResult.success(<#VerificationResult<Transaction>#>)) {
}
However, I get the error: Instance method 'onChange(of:initial:_:)' requires that 'Product.PurchaseResult' conform to 'Equatable'
Also, I'm not sure what the parameter VerificationResult is and how to access it.
Just following up regarding to the question in my previous post. Thank you.
Hi,
I'm trying to implement the code provided in a function within an async function in ContentView. However, I get an error "Value of type 'ContentView' has no member 'checkVerified'"
Hi, the code came from this webpage: https://developer.apple.com/documentation/uikit/using-background-tasks-to-update-your-app
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags:
I have the following code in ContentView:
.onAppear {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "appname.RoutineRefresh", using: nil) { task in
print(task)
handleAppRefresh(task: task as! BGAppRefreshTask)
}
}
However, nothing prints. Additionally, I have print statements in scheduleAppRefresh and handleAppRefresh but nothing prints from those functions either.
I am also calling scheduleTaskRefresh in a .task function.
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags:
Could you elaborate on how to build a model layer and how that differentiates from calling a function from a .task or .onappear function within the view level? What do I need to pass to handleAppRefresh?
import Foundation
import SwiftData
import SwiftUI
import BackgroundTasks
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "app.RoutineRefresh")
// Fetch no earlier than 15 minutes from now.
request.earliestBeginDate = Date(timeIntervalSinceNow: 60)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh: \(error)")
}
}
func handleAppRefresh(task: BGAppRefreshTask) async {
// Schedule a new refresh task.
scheduleAppRefresh()
// Create an operation that performs the main part of the background task.
let operation = RefreshAppContentsOperation()
// Provide the background task with an expiration handler that cancels the operation.
task.expirationHandler = {
operation.cancel()
}
// Inform the system that the background task is complete
// when the operation completes.
operation.completionBlock = {
task.setTaskCompleted(success: !operation.isCancelled)
}
// Start the operation.
//operationQueue.addOperation(operation)
}
final class RefreshAppContentsOperation: Operation, @unchecked Sendable {
@Environment(\.modelContext) private var modelContext
override func main() {
}
}
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags:
When trying to use Product.PurchaseResult or Transaction.updates, or SubscriptionStatus.updates within an .onChange function I get the error:
"Instance method 'onChange(of:initial:_:)' requires that 'Transaction.Transactions' conform to 'Equatable'"
Also, despite clearing purchase history in settings it doesn't seem that the subscription is resetting.
Okay, thank you. And just clarifying, what needs to be passed to the handleAppRefresh function?
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags:
With the code below I get the error:
class BackgroundTasksController: ObservableObject {
func scheduleRoutineResetTask() {
Task {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "app.BackgroundTask", using: nil) { task in
Task {
await self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
}
}
}
private func handleAppRefresh(task: BGAppRefreshTask) async {
// Schedule a new refresh task.
scheduleAppRefresh()
// Create an operation that performs the main part of the background task.
let operation = RefreshAppContentsOperation()
// Provide the background task with an expiration handler that cancels the operation.
task.expirationHandler = {
operation.cancel()
}
// Inform the system that the background task is complete
// when the operation completes.
operation.completionBlock = {
task.setTaskCompleted(success: !operation.isCancelled)
}
// Start the operation.
//operationQueue.addOperation(operation)
}
private func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "app.BackgroundTask")
// Fetch no earlier than 15 minutes from now.
request.earliestBeginDate = Date(timeIntervalSinceNow: 60)
print(request)
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh: \(error)")
}
}
}
final class RefreshAppContentsOperation: Operation, @unchecked Sendable {
}
*** Assertion failure in -[BGTaskScheduler _unsafe_registerForTaskWithIdentifier:usingQueue:launchHandler:], BGTaskScheduler.m:225
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'All launch handlers must be registered before application finishes launching'
*** First throw call stack:
(0x18b5d321c 0x188a6dabc 0x18a8d1670 0x224da17f0 0x224da15f0 0x102fee124 0x102fee24d 0x102fefe1d 0x102feff79 0x19709d241)
libc++abi: terminating due to uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'All launch handlers must be registered before application finishes launching'
*** First throw call stack:
(0x18b5d321c 0x188a6dabc 0x18a8d1670 0x224da17f0 0x224da15f0 0x102fee124 0x102fee24d 0x102fefe1d 0x102feff79 0x19709d241)
terminating due to uncaught exception of type NSException
Is this configuration proper, and with this configuration is.addOperation necessary?
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags:
With this code, I'm getting an error:
import Foundation
import Observation
import StoreKit
enum ProductID: String {
case subscriptionMonthly = "app_monthly"
case subscriptionYearly = "monthly_yearly"
}
@MainActor
@Observable
final class SubscriptionsHandler {
public var activeSubscription: String? = nil
init() {
// Because the tasks below capture 'self' in their closures, this object must be fully initialized before this point.
Task(priority: .background) {
// Finish any unfinished transactions -- for example, if the app was terminated before finishing a transaction.
for await verificationResult in Transaction.unfinished {
await handle(updatedTransaction: verificationResult)
}
// Fetch current entitlements for all product types except consumables.
for await verificationResult in Transaction.currentEntitlements {
await handle(updatedTransaction: verificationResult)
}
}
Task(priority: .background) {
for await verificationResult in Transaction.updates {
await handle(updatedTransaction: verificationResult)
}
}
}
private func handle(updatedTransaction verificationResult: VerificationResult<Transaction>) async {
// The code below handles only verified transactions; handle unverified transactions based on your business model.
guard case .verified(let transaction) = verificationResult else { return }
if let _ = transaction.revocationDate {
// Remove access to the product identified by `transaction.productID`.
// `Transaction.revocationReason` provides details about the revoked transaction.
guard let productID = ProductID(rawValue: transaction.productID) else {
print("Unexpected product: \(transaction.productID).")
return
}
activeSubscription = nil
UserDefaults.standard.set(false, forKey: "isSubscribed")
await transaction.finish()
return
} else if let expirationDate = transaction.expirationDate, expirationDate < Date() {
// In an app that supports Family Sharing, there might be another entitlement that still provides access to the subscription.
activeSubscription = nil
UserDefaults.standard.set(false, forKey: "isSubscribed")
return
} else {
// Provide access to the product identified by transaction.productID.
guard let productID = ProductID(rawValue: transaction.productID) else {
print("Unexpected product: \(transaction.productID).")
return
}
activeSubscription = transaction.productID
UserDefaults.standard.set(true, forKey: "isSubscribed")
await transaction.finish()
return
}
}
}
SwiftUICore/Environment+Objects.swift:34: Fatal error: No Observable object of type SubscriptionsHandler found. A View.environmentObject(_:) for SubscriptionsHandler may be missing as an ancestor of this view.
The SubscriptionsHandler class I have is observable and configured just like the documentation you provided so I'm not sure why I'm getting the error. Also, In the View, the SubscriptionsHandler class is called as an environment variable but is never used. Why is that?
The app no longer crashes, but with my current configuration, the task does not run.
I initialize the task scheduler in the App file's init() function, which calls handleAppRefresh(), which calls RefreshAppContentsOperation()At a given time I call scheduleAppRefresh(), which I thought would preform the task at the scheduled time. The function runs and prints this:
<BGAppRefreshTaskRequest: app.Task, earliestBeginDate: 2025-07-01 21:38:43 +0000>
All of these functions referenced are in my post above. I tried implementing a queue by doing this:
let queue = OperationQueue()
let operation = RefreshAppContentsOperation()
queue.addOperation(operation)
How can I resolve this by Queue or .task?
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags:
I am getting the following error using the breakpoints below. I'm not sure if that indicates anything. It doesn't appear that RefreshAppContentsOperation runs.
App.debug.dylib`partial apply for closure #1 in View.function():
-> 0x103aade10 <+0>: orr x29, x29, #0x1000000000000000
0x103aade14 <+4>: sub sp, sp, #0x20
0x103aade18 <+8>: stp x29, x30, [sp, #0x10]
0x103aade1c <+12>: str x22, [sp, #0x8]
0x103aade20 <+16>: add x29, sp, #0x10
0x103aade24 <+20>: ldr x9, [x22]
0x103aade28 <+24>: str x9, [sp]
0x103aade2c <+28>: mov x8, x29
0x103aade30 <+32>: sub x8, x8, #0x8
0x103aade34 <+36>: str x9, [x8]
0x103aade38 <+40>: ldr x0, [x9, #0x18]
0x103aade3c <+44>: ldr x8, [x22]
0x103aade40 <+48>: mov x10, x29
0x103aade44 <+52>: sub x10, x10, #0x8
0x103aade48 <+56>: str x8, [x10]
0x103aade4c <+60>: str x8, [x9, #0x10]
0x103aade50 <+64>: bl 0x103ad626c ; symbol stub for: swift_task_dealloc
0x103aade54 <+68>: ldr x8, [sp]
0x103aade58 <+72>: ldr x22, [x8, #0x10]
0x103aade5c <+76>: ldr x0, [x22, #0x8]
0x103aade60 <+80>: ldp x29, x30, [sp, #0x10]
0x103aade64 <+84>: and x29, x29, #0xefffffffffffffff
0x103aade68 <+88>: add sp, sp, #0x20
0x103aade6c <+92>: br x0
private func handleAppRefresh(task: BGAppRefreshTask) async {
Task {
let queue = OperationQueue()
scheduleAppRefresh() // breakpoint
print("test") // breakpoint
// Create an operation that performs the main part of the background task.
let operation = RefreshAppContentsOperation() // breakpoint
// Provide the background task with an expiration handler that cancels the operation.
task.expirationHandler = {
operation.cancel()
}
// Inform the system that the background task is complete
// when the operation completes.
operation.completionBlock = {
task.setTaskCompleted(success: !operation.isCancelled)
}
// Start the operation.
queue.addOperation(operation) // breakpoint
}
}
// Schedule a new refresh task.
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "app.BackgroundTask")
// Fetch no earlier than 15 minutes from now.
request.earliestBeginDate = Date(timeIntervalSinceNow: 60)
print(request) // breakpoint
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh: \(error)")
}
}
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags: