Jas*_*son 30 xcode objective-c ios background-fetch
我想让iOS后台应用程序获取在我的应用程序中工作.在Xcode中进行测试时,它可以正常运行,但在设备上运行却没有!
在应用程序中:didFinishLaunchingWithOptions我用setMinimumBackgroundFetchInterval尝试了各种间隔,包括UIApplicationBackgroundFetchIntervalMinimum
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// tell the system we want background fetch
//[application setMinimumBackgroundFetchInterval:3600]; // 60 minutes
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
//[application setMinimumBackgroundFetchInterval:1800]; // 30 minutes
return YES;
}
Run Code Online (Sandbox Code Playgroud)
我已经实现了application:performFetchWithCompletionHandler
void (^fetchCompletionHandler)(UIBackgroundFetchResult);
NSDate *fetchStart;
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
fetchCompletionHandler = completionHandler;
fetchStart = [NSDate date];
[[NSUserDefaults standardUserDefaults] setObject:fetchStart forKey:kLastCheckedContentDate];
[[NSUserDefaults standardUserDefaults] synchronize];
[FeedParser parseFeedAtUrl:url withDelegate:self];
}
-(void)onParserFinished
{
DDLogVerbose(@"AppDelegate/onParserFinished");
UIBackgroundFetchResult result = UIBackgroundFetchResultNoData;
NSDate *fetchEnd = [NSDate date];
NSTimeInterval timeElapsed = [fetchEnd timeIntervalSinceDate:fetchStart];
DDLogVerbose(@"Background Fetch Duration: %f seconds", timeElapsed);
if ([self.mostRecentContentDate compare:item.date] < 0) {
DDLogVerbose(@"got new content: %@", item.date);
self.mostRecentContentDate = item.date;
[self scheduleNotificationWithItem:item];
result = UIBackgroundFetchResultNewData;
}
else {
DDLogVerbose(@"no new content.");
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:60];
localNotification.alertBody = [NSString stringWithFormat:@"Checked for new posts in %f seconds", timeElapsed];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
fetchCompletionHandler(result);
}
Run Code Online (Sandbox Code Playgroud)
我已经(成功!)使用Xcode的Debug/SimulateBackgroundFetch对模拟器和设备进行了测试
我已经成功测试了一个新方案,如另一个SO答案所示(/sf/answers/2094666171/)
在设备上运行但未连接到Xcode时,我的代码没有执行.我打开了应用程序,关闭了应用程序(没有杀死应用程序!),等了几个小时和几天.我已经尝试登录fetch handers,还编写了代码来发送本地通知.
我曾经成功地在设备上看到了我的本地通知测试,事实上iOS似乎触发了三次获取,每次大约相隔大约十五分钟,但之后它再也没有发生过.
我知道用于确定允许背景提取发生频率的算法是一个谜,但我希望它能在一段时间内偶尔运行.
我无法测试其他什么,或者如何解决为什么它似乎在模拟器中工作但不在设备上工作.
感谢任何建议!
Pau*_*w11 27
您的问题是您performFetchWithCompletionHandler
在调用完成处理程序之前返回,因为网络提取操作正在后台进行,您在委托方法中调用完成处理程序.由于iOS认为您不遵守规则,因此它将拒绝您使用后台获取的能力.
要解决您需要调用的问题beginBackgroundTaskWithExpirationHandler
,然后在调用完成处理程序后结束该任务.
就像是:
UIBackgroundTaskIdentifier backgroundTask
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
fetchCompletionHandler = completionHandler;
fetchStart = [NSDate date];
self.backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:self.backgroundUpdateTask];
self.backgroundTask = UIBackgroundTaskInvalid;
}];
[[NSUserDefaults standardUserDefaults] setObject:fetchStart forKey:kLastCheckedContentDate];
[FeedParser parseFeedAtUrl:url withDelegate:self];
}
-(void)onParserFinished
{
DDLogVerbose(@"AppDelegate/onParserFinished");
UIBackgroundFetchResult result = UIBackgroundFetchResultNoData;
NSDate *fetchEnd = [NSDate date];
NSTimeInterval timeElapsed = [fetchEnd timeIntervalSinceDate:fetchStart];
DDLogVerbose(@"Background Fetch Duration: %f seconds", timeElapsed);
if ([self.mostRecentContentDate compare:item.date] < 0) {
DDLogVerbose(@"got new content: %@", item.date);
self.mostRecentContentDate = item.date;
[self scheduleNotificationWithItem:item];
result = UIBackgroundFetchResultNewData;
}
else {
DDLogVerbose(@"no new content.");
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = [NSString stringWithFormat:@"Checked for new posts in %f seconds", timeElapsed];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
fetchCompletionHandler(result);
[[UIApplication sharedApplication] application endBackgroundTask:self.backgroundUpdateTask];
self.backgroundTask = UIBackgroundTaskInvalid;
}
Run Code Online (Sandbox Code Playgroud)
我使用这种方法的测试应用程序最初每15分钟执行一次获取,但随着时间的推移它变得不那么频繁.如果没有后台任务,它会显示您遇到的相同问题.
我发现将背景提取间隔设置为其他内容UIApplicationBackgroundFetchIntervalMinimum
也有帮助.我的测试应用程序运行时的后台获取间隔为3600(一小时),并且已经可靠地触发了几天; 即使手机重启后又没有再运行应用程序.但实际触发间隔为2-3小时.
我的示例应用就在这里
Tec*_*eko 12
为了实现后台提取,您必须做三件事:
背景提取频率
我们的应用程序执行背景提取的频率由系统决定,它取决于:
换句话说,您的应用程序完全受制于为您安排后台获取的系统.此外,每次应用程序使用后台提取时,最多只需30秒即可完成此过程.
包含在AppDelegate中 (将以下代码更改为您的提取需求)
-(void) application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSLog(@"Background fetch started...");
//---do background fetch here---
// You have up to 30 seconds to perform the fetch
BOOL downloadSuccessful = YES;
if (downloadSuccessful) {
//---set the flag that data is successfully downloaded---
completionHandler(UIBackgroundFetchResultNewData);
} else {
//---set the flag that download is not successful---
completionHandler(UIBackgroundFetchResultFailed);
}
NSLog(@"Background fetch completed...");
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return YES;
}
Run Code Online (Sandbox Code Playgroud)
要检查您的应用是否启用了后台刷新,请使用以下代码:
UIBackgroundRefreshStatus status = [[UIApplication sharedApplication] backgroundRefreshStatus];
switch (status) {
case UIBackgroundRefreshStatusAvailable:
// We can do background fetch! Let's do this!
break;
case UIBackgroundRefreshStatusDenied:
// The user has background fetch turned off. Too bad.
break;
case UIBackgroundRefreshStatusRestricted:
// Parental Controls, Enterprise Restrictions, Old Phones, Oh my!
break;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
9919 次 |
最近记录: |