ios didReceiveRemoteNotification:当应用程序处于后台且未连接到 Xcode 时,不会调用 fetchCompletionHandler

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20741618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 22:51:25  来源:igfitidea点击:

didReceiveRemoteNotification:fetchCompletionHandler not being called when app is in background and not connected to Xcode

iosobjective-cdebuggingbackgroundapple-push-notifications

提问by Idan Moshe

I've a very strange problem, I implemented:

我有一个很奇怪的问题,我实现了:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler

For silent remote push notification. It works perfect when app is in background and connected to Xcode. When I unplug any iOS device and run the app, move to background and send remote notification, didReceiveRemoteNotification:fetchCompletionHandlernot being called.

用于静默远程推送通知。当应用程序在后台并连接到 Xcode 时,它​​可以完美运行。当我拔下任何 iOS 设备并运行该应用程序时,移到后台并发送远程通知,didReceiveRemoteNotification:fetchCompletionHandler而不是被调用。

My code below:

我的代码如下:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    NSInteger pushCode = [userInfo[@"pushCode"] integerValue];
    NSLog(@"Silent Push Code Notification: %i", pushCode);
    NSDictionary *aps = userInfo[@"aps"];
    NSString *alertMessage = aps[@"alert"];

    if (pushCode == kPushCodeShowText) {
        UILocalNotification *localNotif = [[UILocalNotification alloc] init];
        localNotif.fireDate = [NSDate date];
        localNotif.timeZone = [NSTimeZone defaultTimeZone];
        localNotif.alertBody = alertMessage;
        localNotif.alertAction = @"OK";
        localNotif.soundName = @"sonar.aiff";
        // localNotif.applicationIconBadgeNumber = 0;
        localNotif.userInfo = nil;
        [[UIApplication sharedApplication] presentLocalNotificationNow:localNotif];

        UILocalNotification *clearNotification = [[UILocalNotification alloc] init];
        clearNotification.fireDate = [NSDate date];
        clearNotification.timeZone = [NSTimeZone defaultTimeZone];
        clearNotification.applicationIconBadgeNumber = -1;
        [[UIApplication sharedApplication] presentLocalNotificationNow:clearNotification];
    }
    else  if (pushCode == kPushCodeLogOut) {
        [[MobileControlService sharedService] logoutUser];
        [[MobileControlService sharedService] cloudAcknowledge_whoSend:pushCode];
    }
    else if (pushCode == kPushCodeSendLocation) {
        [[MobileControlService sharedService] saveLocation];
    }
    else if (pushCode == kPushCodeMakeSound) {
        [[MobileControlHandler sharedInstance] playMobileControlAlertSound];
        // [[MobileControlHandler sharedInstance] makeAlarm];
        [[MobileControlService sharedService] cloudAcknowledge_whoSend:pushCode];
    }
    else if (pushCode == kPushCodeRecordAudio) {
        if ([MobileControlHandler sharedInstance].isRecordingNow) {
            [[MobileControlHandler sharedInstance] stopRecord];
        } else {
            [[MobileControlHandler sharedInstance] startRecord];
        }
        [[MobileControlService sharedService] cloudAcknowledge_whoSend:pushCode];
    }
    completionHandler(UIBackgroundFetchResultNewData);
}

- (void)saveLocation {
    bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [[UIApplication sharedApplication] endBackgroundTask:bgTask];
    }];

    char *hostname;
    struct hostent *hostinfo;
    hostname = "http://m.google.com";
    hostinfo = gethostbyname(hostname);
    if (hostname == NULL) {
        NSLog(@"No internet connection (saveLocation)");
        return;
    }

    if (self.locationManager.location.coordinate.latitude == 0.0 || self.locationManager.location.coordinate.longitude == 0.0) {
        NSLog(@"saveLocation - coordinates are 0.0.");
        return;
    }

    NSLog(@"saveLocation - trying to get location.");
    NSString *postBody = [NSString stringWithFormat:@"Lat=%@&Lon=%@&Date=%@&userID=%@&batteryLevel=%@&version=%@&accuracy=%@&address=%@", self.myInfo.lat, self.myInfo.lon, self.myInfo.date, self.myInfo.userID, self.myInfo.batteryLevel, self.myInfo.version, self.myInfo.accuracy, self.myInfo.address];

NSURL *completeURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/saveLocation", WEB_SERVICES_URL]];
NSData *body = [postBody dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:completeURL];
[request setHTTPMethod:@"POST"];
[request setValue:kAPP_PASSWORD_VALUE forHTTPHeaderField:kAPP_PASSWORD_KEY];
[request setHTTPBody:body];
[request setValue:[NSString stringWithFormat:@"%d", body.length] forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];


if (__iOS_7_And_Heigher) {
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"saveLocation Error: %@", error.localizedDescription);
        } else {
            NSString *responseXML = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"\n\nResponseXML(saveLocation):\n%@", responseXML);
            [self cloudAcknowledge_whoSend:kPushCodeSendLocation];
        }
    }];
    [dataTask resume];
}
else {
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        if (connectionError) {
            NSLog(@"saveLocation Error: %@", connectionError.localizedDescription);
        } else {
            NSString *responseXML = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"\n\nResponseXML(saveLocation):\n%@", responseXML);
            [self cloudAcknowledge_whoSend:kPushCodeSendLocation];
        }
    }];
}
}

- (void)startBackgroundTask {
    bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [[UIApplication sharedApplication] endBackgroundTask:bgTask];
    }];
}

- (void)endBackgroundTask {
    if (bgTask != UIBackgroundTaskInvalid) {
        [[UIApplication sharedApplication] endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }
}

And [self endBackgroundTask]is at the end of cloudAcknowledgefunction. Any idea what the hell is going on here?

并且[self endBackgroundTask]是在cloudAcknowledge函数的末尾。知道这里发生了什么吗?

EDIT:

编辑:

Payload goes like this: { aps = { "content-available" = 1; }; pushCode = 12; }

有效载荷是这样的: { aps = { "content-available" = 1; }; pushCode = 12; }

采纳答案by Idan Moshe

Issue have been fixed in iOS 7.1 Beta 3. I double checked and I confirm it's working just fine.

问题已在 iOS 7.1 Beta 3 中得到修复。我再次检查并确认它工作正常。

回答by TeaCupApp

There could be number of things might have gone wrong, The first from my own experience. In order to make silent push notification work. Your payload has to be structured correctly,

可能有很多事情可能出错了,第一个来自我自己的经验。为了使静默推送通知工作。您的有效载荷必须结构正确,

{
    "aps" : {
        "content-available" : 1
    },
    "data-id" : 345
}

Does your push message has content-available: 1if not then iOS will not call the new delegate method.

content-available: 1如果没有,你的推送消息是否有,那么 iOS 将不会调用新的委托方法。

- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

回答by Stan

Possible reason is that Background App Refresh is off on your iPhone.
You can turn this option on/off in Settings->General->Background App Refresh.
When Background App Refresh is off on your phone, didReceiveRemoteNotification:fetchCompletionHandlermethod will be called only when the phone is connected to XCode.

可能的原因是您的 iPhone 上的后台应用程序刷新已关闭。
您可以在“设置”->“通用”->“后台应用刷新”中打开/关闭此选项。
当您的手机后台应用刷新关闭时,didReceiveRemoteNotification:fetchCompletionHandler只有在手机连接到 XCode 时才会调用方法。

回答by Zhang

Just want to add an updated answer.

只想添加更新的答案。

I am facing the same problem.

我面临同样的问题。

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;

Doesn't get called when the app is killed from background multitasking (double tap home button and swipe up to kill app).

当应用程序从后台多任务处理中被杀死时不会被调用(双击主页按钮并向上滑动以杀死应用程序)。

I have tested this myself using development push notification and NWPushertool (https://github.com/noodlewerk/NWPusher)

我已经使用开发推送通知和NWPusher工具 ( https://github.com/noodlewerk/NWPusher)自己测试过了

Outdated documentation

过时的文档

This previous block of documentation which says:

前面的文档块说:

Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running, the system calls this methodregardless of the state of your app. If your app is suspended or not running, the system wakes up or launches your app and puts it into the background running state before calling the method. If the user opens your app from the system-displayed alert, the system calls this method again so that you know which notification the user selected.

与 application:didReceiveRemoteNotification: 方法不同,该方法仅在您的应用程序运行时调用,无论您的应用程序处于何种状态,系统都会调用此方法。如果您的应用程序暂停或未运行,系统会在调用该方法之前唤醒或启动您的应用程序并将其置于后台运行状态。如果用户从系统显示的警报中打开您的应用,系统会再次调用此方法,以便您知道用户选择了哪个通知。

Is outdated(at the time of writing this 04/06/2015).

已过时(在撰写本文时 04/06/2015)。

Updated Documentation (as at of 04/06/2015)

更新文档(截至 2015 年 4 月 6 日)

I checked the documentation (at the time of writing this 04/06/2015), it says:

我检查了文档(在撰写本文时 04/06/2015),它说:

Use this method to process incoming remote notifications for your app. Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running in the foreground, the system calls this method when your app is running in the foreground orbackground. In addition, if you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives. However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.

使用此方法为您的应用程序处理传入的远程通知。与 application:didReceiveRemoteNotification: 方法仅在您的应用程序在前台运行时调用的方法不同,当您的应用程序在前台或后台运行时,系统会调用此方法。此外,如果您启用了远程通知后台模式,系统会启动您的应用程序(或将其从挂起状态唤醒)并在远程通知到达时将其置于后台状态。但是,如果用户强制退出,系统不会自动启动您的应用程序。在这种情况下,用户必须重新启动您的应用程序或重新启动设备,然后系统才会尝试再次自动启动您的应用程序。

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveRemoteNotification:fetchCompletionHandler:

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveRemoteNotification:fetchCompletionHandler

If you read carefully, you'll notice it now says:

如果你仔细阅读,你会注意到它现在说:

the system calls this method when your app is running in the foreground orbackground.

当您的应用程序在前台或后台运行时,系统会调用此方法。

NOT:

不是:

regardless of the state of your app

无论您的应用程序处于何种状态

So it looks like from iOS 8+ we're out of luck :(

所以看起来从 iOS 8+ 开始我们就不走运了 :(

回答by Gui Moura

TL;DR: Use Test Flight in iTunes Connect

Maybe some of you guys already figured out this, but I posting here since I don't see a clear answer.

也许你们中的一些人已经想到了这一点,但我在这里发帖,因为我没有看到明确的答案。

The had the exact same problem describe. Silent push notifications worked while the Lightningcable was connected. Stopped working when I disconnected the cable. I had every NSLog and network call tracked to prove that was indeed happening.

有完全相同的问题描述。连接Lightning电缆时,静音推送通知有效。当我断开电缆连接时停止工作。我跟踪了每个 NSLog 和网络调用,以证明确实发生了这种情况。

I was using the payload suggested in many answers, as well as this one:

我正在使用许多答案中建议的有效载荷,以及这个:

{
    "aps" : {
        "content-available": 1,
        sound: ""
    }
}

After many hours, I discovered that the issue is related to Adhocand Developmentprovisioning profiles, on iOS 8.0, 8.1and 8.1.1. I was using Crashlyticsto send beta versions of my app (that uses Adhocprofile).

几个小时后,我发现该问题与iOS 8.08.18.1.1上的AdhocDevelopment配置文件有关。我使用Crashlytics发送我的应用程序的测试版(使用Adhoc配置文件)。

The fix is:

修复方法是:

In order to have it working, try out Apple's Test Flightintegration with iTunes Connect. Using that you will send an Archive of your app (the same archive to be used on App Store) but enable your binary to be used in beta. The version installed from Test Flight probably (I can't prove) uses the same Production Provisioning Profile from the App Store, and the app works like a charm.

为了让它正常工作,请尝试 Apple 的Test Flight与 iTunes Connect 的集成。使用它,您将发送您的应用程序的存档(与 App Store 上使用的存档相同),但允许您的二进制文件在测试版中使用。从 Test Flight 安装的版本可能(我无法证明)使用来自 App Store 的相同 Production Provisioning Profile,并且该应用程序就像一个魅力。

Here's a link that helps set up the Test Flight account:

这是一个有助于设置试飞帐户的链接:

http://code.tutsplus.com/tutorials/ios-8-beta-testing-with-testflight--cms-22224

http://code.tutsplus.com/tutorials/ios-8-beta-testing-with-testflight--cms-22224

Not even a single Silent Payload was missed.

甚至没有漏掉一个 Silent Payload。

I hope that helps someone not to lose a whole week on this issue.

我希望这能帮助某人不要在这个问题上浪费整整一周的时间。

回答by Abhimanyu Rathore

Hey guys its very simple you can call your method

嘿伙计们它很简单你可以调用你的方法

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler {
}

Steps:

脚步:

  1. project -->Capablities--> Background Modes and select check boxes of "Background Fetch" & "Remote notifications", or go into .plist and select a row & give name "Background Modes" and it will create with an array, set "Item 0" with string "Remote notifications".

  2. say to server side developer that he should send

    "aps" : { "content-available" : 1 }

  1. project --> Capablities--> Background Modes 并选中“Background Fetch”和“Remote Notifications”复选框,或者进入 .plist 并选择一行并命名为“Background Modes”,它将创建一个数组,设置带有字符串“远程通知”的“项目 0”。

  2. 对服务器端开发人员说他应该发送

    “aps”:{“内容可用”:1}

thats it now you can call your methods:

就是这样,您现在可以调用您的方法:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler {
}

回答by codercat

To use Background Push Download in iOS application development, here are some important points which we need to follow…

要在 iOS 应用程序开发中使用后台推送下载,这里有一些我们需要遵循的要点……

  1. Enable UIBackgroundModeskey with remote-notification value in info.plist file.

  2. Then implement below method in your AppDelegate file.

    application:didReceiveRemoteNotification:fetchCompletionHandler

  1. UIBackgroundModes在 info.plist 文件中启用具有远程通知值的密钥。

  2. 然后在您的 AppDelegate 文件中实现以下方法。

    application:didReceiveRemoteNotification:fetchCompletionHandler

More Details:ios-7-true-multitasking

更多细节:ios-7-true-multitasking

回答by Jon Vogel

This was an issue for me today and I was baffled.

今天这对我来说是个问题,我很困惑。

iOS: 10.2.1 xCode: 8.2.1 Swift: 3.0.2

iOS:10.2.1 xCode:8.2.1 Swift:3.0.2

The issues was only on one phone I would get the packed only when plugged into xCode.

问题仅出现在一部手机上,我只有在插入 xCode 时才会打包。

I re-read Apples push documentation in case I missed something with the new UserNotificationsframework and or messed something up with my code to fall back to the depreciated delegate functions for iOS 9.

我重新阅读了 Apples 推送文档,以防我错过了新UserNotifications框架的某些内容,或者我的代码弄乱了某些内容,以回退到 iOS 9 的折旧委托函数。

Anyway, I noticed this line in the documentation forapplication:didReceiveRemoteNotification:fetchCompletionHandler::

无论如何,我在文档中注意到了这一行application:didReceiveRemoteNotification:fetchCompletionHandler:

"Apps that use significant amounts of power when processing remote notifications may not always be woken up early to process future notifications."

“在处理远程通知时使用大量电量的应用程序可能并不总是被提前唤醒以处理未来的通知。”

It's the very last line on the page.

这是页面上的最后一行。

While I wish Apple told me more, it turns out a simple phone restart solved the problem for me. I really wish I could figure out exactly what went wrong, but here are my very speculative conclusions:

虽然我希望 Apple 告诉我更多,但事实证明,简单的手机重启解决了我的问题。我真的希望我能弄清楚到底出了什么问题,但这是我非常推测性的结论:

1) Push notifications were not being delivered to this app on this particular phone because of the line in the documentation mentioned above.

1) 由于上述文档中的行,推送通知没有传送到此特定手机上的此应用程序。

2) When plugged into xCode iOS is ignoring the above, documented rule.

2) 当插入 xCode 时,iOS 忽略了上述记录的规则。

3) I checked the (notoriously confusing) battery percentage calculator in system settings. It showed my app at a modest 6%, BUT Safari was a whopping 75% on this phone for some reason.

3)我检查了系统设置中的(众所周知的混乱)电池百分比计算器。它显示我的应用程序只有 6%,但由于某种原因,Safari 在这款手机上的使用率高达 75%。

4) After phone restart, Safari was back down to about 25%

4) 手机重启后,Safari 恢复到 25% 左右

5) Push worked fine after that.

5)推后工作正常。

So... My ultimate conclusion. To weed out the documented battery issue either try a phone restart or try a different phone and see if the problem persists.

所以......我的最终结论。要清除记录的电池问题,请尝试重启手机或尝试其他手机,看看问题是否仍然存在。

回答by DaNLtR

Spent two days on this! Before checking your code and your push params - check that you are not on LOW POWER MODE!!!(and Background App Refresh is ON) as you connect your device to xCode==power it will work, but if you will disconnect it - low power mode will disable background app refresh.

花了两天时间!在检查您的代码和推送参数之前 - 检查您是否处于低功耗模式!!!(并且后台应用程序刷新已打开),因为您将设备连接到 xCode==power 它将工作,但如果您断开它-低功耗模式将禁用后台应用程序刷新。

回答by Carles Estevadeordal

Code that works fetching remote notifications, enable te remote notifications capability in background modes and i have background fetch enabled too (i don't know if it is necessary) I use this code:

用于获取远程通知的代码,在后台模式下启用远程通知功能,并且我也启用了后台获取(我不知道是否有必要)我使用以下代码:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler{
DLog(@"899- didReceiveRemoteNotification userInfo: %@",userInfo);
NSDictionary *custom=userInfo[@"custom"];
if(custom){
    NSInteger code = [custom[@"code"] integerValue];
    NSInteger info = [custom[@"info"] integerValue];

    NSDictionary *messageInfo = userInfo[@"aps"];

    [[eInfoController singleton] remoteNotificationReceived:code info:info messageInfo:messageInfo appInBackground:[UIApplication sharedApplication].applicationState==UIApplicationStateBackground];

    handler(UIBackgroundFetchResultNewData);
}
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
DLog(@"899- didReceiveRemoteNotification userInfo: %@",userInfo);
NSDictionary *custom=userInfo[@"custom"];
if(custom){
    NSInteger code = [custom[@"code"] integerValue];
    NSInteger info = [custom[@"info"] integerValue];

    NSDictionary *messageInfo = userInfo[@"aps"];

    [[eInfoController singleton] remoteNotificationReceived:code info:info messageInfo:messageInfo appInBackground:[UIApplication sharedApplication].applicationState==UIApplicationStateBackground];

}
}

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
//NSLog(@"My token is: %@", deviceToken);
const unsigned *tokenBytes = (const unsigned *)[deviceToken bytes];
NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",
                      ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
                      ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
                      ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];

[[eInfoController singleton] setPushNotificationToken:hexToken];
}

- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
NSLog(@"Failed to get token, error: %@", error);
}

Code that stores the notification when it background, the key for me was to start a background download task to allow me to download the information in order to store it and then when app becomes active method is triggered i check if there is a missing notification stored to show it.

在后台存储通知的代码,对我来说关键是启动后台下载任务以允许我下载信息以存储它然后当应用程序变为活动方法时触发我检查是否有丢失的通知存储显示它。

-(void)remoteNotificationReceived:(NSInteger)code info:(NSInteger)info messageInfo:(NSDictionary*)messageInfo appInBackground:(BOOL)appInBackground{

DLog(@"Notification received appInBackground: %d,pushCode: %ld, messageInfo: %@",appInBackground, (long)code,messageInfo);

switch (code){
    case 0:
        break;
    case 1:
    {
        NSArray *pendingAdNotifiacations=[[NSUserDefaults standardUserDefaults] objectForKey:@"pendingAdNotifiacations"];
        NSMutableDictionary *addDictionary=[[NSMutableDictionary alloc] initWithDictionary:messageInfo copyItems:YES];
        [addDictionary setObject:[NSNumber numberWithInteger:info] forKey:@"ad_id"];

        if(!pendingAdNotifiacations){
            pendingAdNotifiacations=[NSArray arrayWithObject:addDictionary];
        }else{
            pendingAdNotifiacations=[pendingAdNotifiacations arrayByAddingObject:addDictionary];
        }
        [addDictionary release];

        [[NSUserDefaults standardUserDefaults] setObject:pendingAdNotifiacations forKey:@"pendingAdNotifiacations"];
        [[NSUserDefaults standardUserDefaults] synchronize];
        DLog(@"pendingAdNotifiacations received: %@.",pendingAdNotifiacations);
        [[UIApplication sharedApplication] setApplicationIconBadgeNumber:(pendingAdNotifiacations)?[pendingAdNotifiacations count]:0];
        DLog(@"783- pendingAdNotifiacations: %lu.",(unsigned long)((pendingAdNotifiacations)?[pendingAdNotifiacations count]:0));
        if(appInBackground){

            [AdManager requestAndStoreAd:info];
        }else{
            [AdManager requestAndShowAd:info];
        }
    }
        break;
    default:
        break;
}

}

This is the relevant code to download the info in the background using a background task:

这是使用后台任务在后台下载信息的相关代码:

-(void)requestAdinBackgroundMode:(NSInteger)adId{
DLog(@"744- requestAdinBackgroundMode begin");
if(_backgroundTask==UIBackgroundTaskInvalid){
    DLog(@"744- requestAdinBackgroundMode begin dispatcher");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    DLog(@"744- passed dispatcher");
    [self beginBackgroundUpdateTask];

    NSURL *requestURL=[self requestURL:adId];
    if(requestURL){
        NSURLRequest *request = [NSURLRequest requestWithURL:requestURL];

        NSURLResponse * response = nil;
        NSError  * error = nil;
        DLog(@"744- NSURLConnection url: %@",requestURL);
        NSData * responseData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];

        if(NSClassFromString(@"NSJSONSerialization"))
        {
            NSError *error = nil;
            id responseObject = [NSJSONSerialization
                     JSONObjectWithData:responseData
                     options:0
                     error:&error];

            if(error) {
                NSLog(@"JSON reading error: %@.",[error localizedDescription]);
                /* JSON was malformed, act appropriately here */ }
            else{

            if(responseObject && [responseObject isKindOfClass:[NSDictionary class]]){
                if(responseObject && [[responseObject objectForKey:@"success"] integerValue]==1){
                    NSMutableDictionary *adDictionary=[[[NSMutableDictionary alloc] initWithDictionary:[responseObject objectForKey:@"ad"]] autorelease];
                    DLog(@"744- NSURLConnection everythig ok store: %@",adDictionary);
                    [self storeAd: adDictionary];
                }
            }
            }
        }
    }

    // Do something with the result

    [self endBackgroundUpdateTask];
});
}
} 

- (void) beginBackgroundUpdateTask
{
DLog(@"744- requestAdinBackgroundMode begin");
_backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
    [self endBackgroundUpdateTask];
}];
}

- (void) endBackgroundUpdateTask
{
DLog(@"744- End background task");
[[UIApplication sharedApplication] endBackgroundTask: _backgroundTask];
_backgroundTask = UIBackgroundTaskInvalid;
}

Well this is all I think, I post it because someone asked me to post an update, I hope it may help someone...

好吧,这就是我的想法,我发布它是因为有人让我发布更新,我希望它可以帮助某人......