ApplicationWillTerminate NSURLSession 可能吗?

ApplicationWillTerminate NSURLSession Possible?

我试图在应用程序终止时通过 NSURLSession 快速 POST。应用程序终止定义为用户在主屏幕上将其滑出。此外,applicationWillTerminate 被示范性地调用(所以这不是问题)。

我的目的是通知服务器该用户正在下线。

但是,这不起作用.. 因为我的后端没有收到 POST。我想弄清楚为什么这不起作用.. 或者即使它应该?根据 Apple 文档,如果它可以在 5 秒内执行,这应该可以工作。虽然我什至没有完成处理程序,所以它应该被执行。任何帮助或建议将不胜感激。

我的实现如下(供参考)

- (void)applicationWillTerminate:(UIApplication *)application {

    NSMutableDictionary * gatherAllInputs = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
                                             @"blah@df.com, @"emailEntry",
                                             @"False", @"isPersonAvailable",
                                             nil];

    NSError *error;
    NSData *gatherAllInputsJSON = [NSJSONSerialization dataWithJSONObject:gatherAllInputs options:0 error:&error];

    NSString* theDataSentToServer;
    theDataSentToServer = [[NSString alloc] initWithData:gatherAllInputsJSON encoding:NSUTF8StringEncoding];

    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *postingSession = [NSURLSession sessionWithConfiguration:sessionConfiguration];

    NSURL *url = [NSURL URLWithString:@"https://blahblahblah.com/someblah"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:[theDataSentToServer dataUsingEncoding:NSUTF8StringEncoding]];

    NSURLSessionDataTask *postSomething = [postingSession dataTaskWithRequest:request];
    [postSomething resume]; 
    NSLog(@"Got here!"); //<-- THIS GETS OUTPUTTED.. SO I KNOW THIS CODE IS BEING CALLED!

}

编辑:

同样,我们有带有 XMPP 框架的消息传递应用程序。 要求 terminate/Disconnect applicationWIllTerminate 委托上的 XMPP 连接。实际上,当应用程序处于前台并且用户切换到多任务处理时,将调用 applicationWIllTerminate UI(双击主页按钮)。通过调用 XMPP Disconnection 尝试但没有运气。

不能使用 WillResignActive 断开连接,在 DidEnteredBackground 中不允许任何时间延长委托这种情况。

Server-client Ping pong 每 2 分钟运行一次,因此也继续中继。

寻找在用户强制退出应用程序时断开 XMPP 的可行解决方案。

可能会发生很多事情:

首先,苹果说:"Your implementation of this method has approximately five seconds to perform any tasks and return." Apple Docs

我强调"approximately"是因为把这5秒视为理所当然不是你通常想做的事情。此超时可能取决于多种因素,例如资源的总体可用性(受您的应用无法控制的具体情况的影响,例如其他应用 运行)。

其次,你说:"although I don't even have a completion handler so it should be executed"。

这意味着您正在执行同步调用,即必须 等待 才能放手的调用。您确定零到 大约 5 秒足以完成此调用吗?我知道这听起来时间太多了,但网络 availability/reliability/speed 也是我们通常不应认为理所当然的东西。

您是否尝试过做其他事情而不是在那里进行网络呼叫?例如,为用户默认值写点什么?放一个计时器,看看实际给你多少时间有什么变化。

问题不在于,5 秒(或类似 5 秒的时间)时间不够。而且您不会同步启动任务,因为您没有处理程序。依旧是异步调用。

-applicationWillTerminate: 在应用程序关闭时发送。当它 returns 时,应用程序 击落,即使有额外的后台任务。所以后台任务也停止了。因此后台任务只有几毫秒或更短的时间才能完成。

您可以使用同步请求,因此在请求完成之前 -applicationWillTerminate: 不会 return。然而,这从来都不是一个好主意,而且在 -applicationWillTerminate: 中肯定不是。如果你想告诉服务器,应用程序已经消失,只需执行一个心跳。这还有一个额外的好处,即在不发送 -applicationWillTerminate: 的情况下退出的应用程序也会被取消注册。 (即在发生崩溃的情况下。)

我遇到了完全相同的情况:NSURLSession 在 applicationWillTerminate: 过程中不起作用。

但是如果iOS没有给你5秒时间完成你的任务,你可以自己接:

sleep (3);

applicationWillTerminate: 结束时给了我足够的时间来执行所有最终网络 activity。其实延迟1秒也可以。