SwiftUI 和 .backgroundTask(.appRefresh(..)) 不工作

iKK*_*iKK 5 task ios background-task swiftui

使用iOS16.1、Swift5.7.1、XCode 14.1、

我的 SwiftUI 应用程序将完成一些后台工作。

第一个问题:定期发生的后台工作只能在应用程序仍在运行时才能完成(即,如果应用程序没有完全关闭而是被其他应用程序覆盖),这是否正确?或者您可以使用完全封闭的应用程序定期执行后台工作吗?如果是,怎么办?

第二个问题:下面的代码有什么问题?

不幸的是,这段代码没有完成任何后台工作,为什么?(我尝试过使用和不使用调试器,而且我也在实际设备上尝试过)

(当然,我已经在info.plist中输入了必要的信息并添加了后台功能)

import SwiftUI
import BackgroundTasks

@main
struct MyApp: App {
    
    @Environment(\.scenePhase) private var phase
    
    @State private var counter = 0;
    
    var body: some Scene {
        WindowGroup {
            ZStack {
                Text("\(counter)")
            }
        }
        .onChange(of: phase) { newPhase in
            switch newPhase {
            case .background:
                scheduleDataRefetch()
            default: break
            }
        }
        .backgroundTask(.appRefresh("com.url.myidentifier")) {
            await refetch()
            scheduleDataRefetch()
        }
    }
    
    private func refetch() async {
        if await refetchData() {
            print("refetch done...")
        }
    }
    
    private func refetchData() async -> Bool {
        
        counter += 1
        print(counter)
        
        return true
    }
}

func scheduleDataRefetch() {
    
    let request = BGAppRefreshTaskRequest(identifier: "com.url.myidentifier")
    request.earliestBeginDate = .now.addingTimeInterval(5)
    do {
        try BGTaskScheduler.shared.submit(request)
        // HERE I SET THE BREAKPOINT IF WORKING WITH DEBUGGER
        print("Background Task scheduled..")
    } catch {
        print("Could not first-time schedule app refresh: \(error)")
    }
}
Run Code Online (Sandbox Code Playgroud)

我在 lldb 中使用以下行来执行调试器中的实际后台任务:

e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.url.myidentifier"]
Run Code Online (Sandbox Code Playgroud)

当我在注册后立即设置断点时,我可以通过 lldb 调试器终端执行上述行,使后台任务准确运行一次。但是,当我第二次尝试时,会出现以下错误。为什么 ?

我收到的错误消息是:

2022-11-16 15:08:54.801942+0100 myApp[5035:1253266] Simulating launch for task with identifier com.url.myidentifier
Background Task scheduled..
2022-11-16 15:08:56.215666+0100 myApp[5035:1253265] Marking simulated task complete: <BGAppRefreshTask: com.url.myidentifer>
2022-11-16 15:08:56.218075+0100 myApp[5035:1253298] Task with identifier <decode: missing data> is already running
2022-11-16 15:08:56.221317+0100 myApp[5035:1253298] *** Assertion failure in -[BGTaskScheduler _simulateLaunchForTaskWithIdentifier:], BGTaskScheduler.m:591
2022-11-16 15:08:56.230648+0100 myApp[5035:1253298] [xpc.exceptions] <NSXPCConnection: 0x2825850e0> connection to service with pid 76 named com.apple.duetactivityscheduler: Exception caught during invocation of reply block to message 'getPendingTaskRequestsWithCompletionHandler:'.

Exception: No launch handler registered for task with identifier {public}@
(
    0   CoreFoundation                      0x00000001a33d9e94 5CDC5D9A-E506-3740-B64E-BB30867B4F1B + 40596
    1   libobjc.A.dylib                     0x000000019c7138d8 objc_exception_throw + 60
    2   Foundation                          0x000000019dd01b4c C431ACB6-FE04-3D28-B677-4DE6E1C7D81F + 5528396
    3   BackgroundTasks                     0x000000020a9e9880 5AF8F9BB-273F-3BE1-AC5A-A4A6929CC5E0 + 22656
    4   BackgroundTasks                     0x000000020a9e806c 5AF8F9BB-273F-3BE1-AC5A-A4A6929CC5E0 + 16492
    5   CoreFoundation                      0x00000001a3444704 5CDC5D9A-E506-3740-B64E-BB30867B4F1B + 476932
    6   CoreFoundation                      0x00000001a33f0b6c 5CDC5D9A-E506-3740-B64E-BB30867B4F1B + 133996
    7   Foundation                          0x000000019d85db08 C431ACB6-FE04-3D28-B677-4DE6E1C7D81F + 662280
    8   Foundation                          0x000000019d82eef0 C431ACB6-FE04-3D28-B677-4DE6E1C7D81F + 470768
    9   Foundation                          0x000000019de082e4 C431ACB6-FE04-3D28-B677-4DE6E1C7D81F + 6603492
    10  libxpc.dylib                        0x00000001f0490f1c 7A0CA8D2-7285-37DD-AE97-2EFAA1DE763E + 122652
    11  libxpc.dylib                        0x00000001f0483fb4 7A0CA8D2-7285-37DD-AE97-2EFAA1DE763E + 69556
    12  libdispatch.dylib                   0x00000001097120dc _dispatch_client_callout3 + 20
    13  libdispatch.dylib                   0x0000000109731df0 _dispatch_mach_msg_async_reply_invoke + 392
    14  libdispatch.dylib                   0x0000000109719ea8 _dispatch_lane_serial_drain + 376
    15  libdispatch.dylib                   0x000000010971ae34 _dispatch_lane_invoke + 420
    16  libdispatch.dylib                   0x0000000109727cbc _dispatch_workloop_worker_thread + 740
    17  libsystem_pthread.dylib             0x00000001f042fdf8 _pthread_wqthread + 288
    18  libsystem_pthread.dylib             0x00000001f042fb98 start_wqthread + 8
)
2022-11-16 15:08:56.234625+0100 myApp[5035:1253298] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'No launch handler registered for task with identifier {public}@'
*** First throw call stack:
(0x1a33d9e88 0x19c7138d8 0x19dd01b4c 0x20a9e9880 0x20a9e806c 0x1a3444704 0x1a33f0b6c 0x19d85db08 0x19d82eef0 0x19de082e4 0x1f0490f1c 0x1f0483fb4 0x1097120dc 0x109731df0 0x109719ea8 0x10971ae34 0x109727cbc 0x1f042fdf8 0x1f042fb98)
libc++abi: terminating with uncaught exception of type NSException
Run Code Online (Sandbox Code Playgroud)

我不太关心 lldb 终端中的调试器不工作(我们现在使用的不是所有东西都适用于 XCode) - 但我真的很想知道为什么代码也不适用于实际设备。对此的任何帮助都非常感谢!

mor*_*wan -1

尝试改变

private func refetch() async {
Run Code Online (Sandbox Code Playgroud)

public func refetch() async {
Run Code Online (Sandbox Code Playgroud)