서비스 연결을 유지하고 이벤트 (호출)를 받기 위해 긴 폴링 메커니즘을 사용하는 VoIP iOS 앱이 있습니다. 즉, NSURLConnection
은 몇 분 동안 보류 중이지만 이벤트가 발생한 직후에 반환됩니다. VoIP 플래그로 인해, 앱이 백그라운드 모드 인 동안 Keep Alive 핸들러를 설정하고 업데이트를받을 수 있습니다.iOS : NSURLConnection 콜백이 많이 지연되거나 실행되지 않습니다.
그러나 대부분의 경우이 작업은 이지만 신뢰할 수는 없습니다.. 경우에 따라 NSURLConnection
콜백이 너무 지연되거나 요청이 시간 초과 된 후에도 전혀 실행되지 않을 수 있습니다 (timeoutInterval
에 NSURLRequest
에 도달).
로그의 예는 명확히 :
는-
이 앱은 백그라운드 모드
NSURLConnection
# 1 (긴 설문 조사) (부팅시 시스템에 의해 시작됩니다)에서 실행- 이 시작 반환 후 1 새로운 데이터
NSURLConnection
# 2 (긴 설문 조사)와 분 시작되고 15 일 이후 수익률은 새로운 데이터없이 (서버 측 최대) 의사록- (...)
- 01,230,834,878,966,146,532 10 # 99 (long poll)이 시작되지만 복귀하지 않습니다.
timeoutInterval
이 만료 된 후에도 (16 분) - 때때로 keep alive 핸들러가 호출되며 아무 것도 발생하지 않습니다.
backgroundTimeRemaining
속성의 값이 비현실적입니다 (180.0
대신179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0
). - 1 시간 후 사용자가 앱을 엽니 다. 이 앱은
NSURLRequest
들과 receivce 응답 일부 secounds 후 - 다양한 실행할 수, 사용자가 10 분 이상 후 응용 프로그램
- 을 닫고는
NSURLConnection
# 99 콜백didFailWithError
는 시간 초과 오류 (-1001)로 해고. 이 요청의 실행 시간은 심지어timeoutInterval
의 경우 16 분으로 제한되어 있었지만 이후에 초기화되었지만 이전에 완료된 다른 여러 요청에 한 시간 이상 걸렸습니다.
내 관점에서 볼 때, 이것은 iOS의 매우 이상한 행동처럼 보입니다. 왜 iOS가 백그라운드 실행 시간을 앱에 제공하고 Keep Alive 핸들러를 호출해야하지만 NSURLConnection 콜백을 제대로 실행하지 않아야합니까?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{
NSLog(@"########### Started Keep-Alive Handler ###########");
[self startBackgroundHandler:YES timeout:30];
NSLog(@"########### Completed Keep-Alive Handler ###########");
}];
[self startBackgroundHandler:NO timeout:60];
}
-(void)startBackgroundHandler:(BOOL)force timeout:(int)timeout {
UIApplicationState currentAppState = [[UIApplication sharedApplication] applicationState];
BOOL appIsBackground = currentAppState == UIApplicationStateBackground;
if(appIsBackground || force) {
int localThreadId = ++_currentBackgroundThreadId;
__block UIBackgroundTaskIdentifier bgTask;
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
NSLog(@"Cleaning up [Background Thread %d] ...", localThreadId);
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
NSLog(@"startBackgroundHandler with [Background Thread %d] appIsBackground=%d force=%d", localThreadId, appIsBackground, force);
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if(_currentBackgroundThreadId == localThreadId) {
NSLog(@"[Background Thread %d] Background time left: %0.1f", localThreadId, [UIApplication
sharedApplication].backgroundTimeRemaining);
sleep(timeout);
}
NSLog(@"[Background Thread %d] Will exit...", localThreadId);
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
} else {
NSLog(@"Ignored startBackgroundHandler - appIsBackground=%d force=%d", appIsBackground, force);
}
}
모든 NSURLConnections
가 가지고 runloop을 - 다음과 같이가 시작됩니다 :살아 핸들러를 유지
NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:mrequest delegate:self startImmediately:NO];
if(connection) {
[connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[connection start];
} else {
// error handling...
}
는 PS : 응용 프로그램의 이전 버전에서, data fetch
배경을 사용 모드 대신 voip
, 그리고 그런 종류의 문제를 만난 적이.