所以我想构建一个iOS,我对objective-c的世界很陌生,我想要实现的一个功能是能够发送API请求并在应用程序不是“焦点/焦点”时进行一些后台处理在后台”。我已经研究了几天关于这个 BG任务适用于 iOS 13 的 API 并创建了一个项目,以查看我是否可以让“后台获取”正常工作。我已经不能了。我很确定我的所有设置都正确,但我无法在我的 iPhone 上触发后台获取功能,在过去几天甚至一次都没有。
这是我的代码。这一切只是一个使用objective-c的空白iOS项目。我只编辑了 AppDelegate.m 和 Info.plist
AppDelegate.m
#import "AppDelegate.h"
#import <BackgroundTasks/BackgroundTasks.h>
static NSString* TaskID = @"com.myapp.task";
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:TaskID
usingQueue:nil
launchHandler:^(BGProcessingTask *task) {
[self handleAppRefreshTask:task];
}];
return YES;
}
#pragma mark - UISceneSession lifecycle
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
-(void)handleAppRefreshTask:(BGProcessingTask *)task {
//do things with task
NSLog(@"Process started!");
task.expirationHandler = ^{
NSLog(@"WARNING: expired before finish was executed.");
};
NSString *targetUrl = @"https://webhook.site/1b274a6f-016f-4edf-8e31-4ed7058eaeac";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:@"GET"];
[request setURL:[NSURL URLWithString:targetUrl]];
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:
^(NSData * _Nullable data,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
NSString *myString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Data received: %@", myString);
}] resume];
task.expirationHandler = ^{
NSLog(@"WARNING: expired before finish was executed.");
};
[task setTaskCompletedWithSuccess:YES];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(@"Entering background");
BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:TaskID];
request.requiresNetworkConnectivity = true;
request.requiresExternalPower = false;
request.earliestBeginDate = [NSDate dateWithTimeIntervalSinceNow:60];
@try {
[[BGTaskScheduler sharedScheduler] submitTaskRequest:request error:nil];
}
@catch(NSException *e){
NSLog(@" Unable to submit request");
}
}
@end
iOS 13 中的后台获取是否中断?即使在 Xcode 调试菜单中单击“模拟后台提取”也不起作用。它只是关闭了应用程序,没有任何 react 。任何人都可以帮助/提供任何建议吗?
最佳答案
几点观察:
setTaskCompletedWithSuccess
应该在网络请求的完成处理程序中。在请求有机会运行并且您已处理结果之前,您不希望将任务标记为完成。 submitTaskRequest
, 但通过 nil
对于NSError
引用。您还将其包装在异常处理程序中。但是这个 API 调用不会抛出异常,而只是将错误传回。但是您必须为其提供错误引用。例如。NSLog(@"Entering background");
BGProcessingTaskRequest *request = [[BGProcessingTaskRequest alloc] initWithIdentifier:TaskID];
request.requiresNetworkConnectivity = true;
request.requiresExternalPower = false;
request.earliestBeginDate = [NSDate dateWithTimeIntervalSinceNow:60];
NSError *error;
if (![[BGTaskScheduler sharedScheduler] submitTaskRequest:request error:&error]) {
NSLog(@"BGTaskScheduler failed: %@", error);
}
在你的代码中,如果它失败了,你永远不会知道。
applicationDidEnterBackground
.即,您是否看到此“进入后台”消息?我问的原因是如果你提供了一个场景委托(delegate)(如果你刚刚创建了一个新的 iOS 13 应用程序很常见),这个方法将不会被调用,而 sceneDidEnterBackground
将要。 BGAppRefreshTask
)。您创建了一个后台任务(BGProcessingTask
),这是另一回事。要测试后台处理请求,请参阅 Starting and Terminating Tasks During Development . NSLog
(假设您将应用程序附加到 Xcode 调试器)。我建议在不将应用程序附加到 Xcode 的情况下对此进行测试。有几个选项:os_log
即使 Xcode 未运行,我的设备也会从 macOS 控制台发出语句。这在记录应用程序/场景方法时非常有用。参见 WWDC 2016 Unified Logging and Activity Tracing 无论你做什么,对于后台处理、后台应用程序刷新等,我都会编写一些机制,以便我可以检查请求/任务是否发生,即使没有附加到 Xcode。在某些情况下,附加到调试器会影响应用程序的生命周期,我想确保我有一些方法可以在没有控制台优势的情况下确认正在发生的事情。
有关更多信息,请参阅 WWDC 2019 视频 Advances in App Background Execution .
关于ios - 如何在 iOS 13 中使用 Objective-c 中的 BGTask(后台获取),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62026107/