NSTimer прекращает запуск в фоновом режиме через некоторое время

Эй, я разрабатываю приложение, в котором я должен запускать API каждые 30 секунд, поэтому я создал NSTimer для него. Но когда мое приложение переходит в фоновый таймер, он прекращает стрельбу через 3-4 минуты. Таким образом, он работает только 3-4 минуты в фоновом режиме, но не после этого. Как я могу изменить свой код, чтобы таймер не останавливался.

Вот некоторые из моего кода.

- (IBAction)didTapStart:(id)sender { NSLog(@"hey im in the timer ..%@",[NSDate date]); [objTimer invalidate]; objTimer=nil; UIBackgroundTaskIdentifier bgTask = UIBackgroundTaskInvalid; UIApplication *app = [UIApplication sharedApplication]; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; }]; objTimer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:self selector:@selector(methodFromTimer) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:objTimer forMode:UITrackingRunLoopMode]; } -(void)methodFromTimer{ [LOG debug:@"ViewController.m ::methodFromTimer " Message:[NSString stringWithFormat:@"hey im from timer ....%@",[NSDate date] ]]; NSLog(@"hey im from timer ....%@",[NSDate date]); } 

Я даже изменил код следующим образом:

 [[NSRunLoop mainRunLoop] addTimer:objTimer forMode:NSRunLoopCommonModes]; 

Это тоже не сработало.

Не создавайте задачу UIBackgroundTaskIdentifier как локальную и делайте ее глобальной, как показано ниже:

Шаг 1

Инициирующая разновидность

Шаг 2

Метод ViewDidLoad и добавленный barButton

Шаг 3

Вызов метода BarButton

Шаг -4

Вызов метода таймера

Поскольку локального свободного пространства и глобального не будет, и я создал демонстрационную версию и запускал ее на некоторое время с повторным таймером на 1 секунду и работал плавно. Тем не менее, если у вас возникли проблемы, сообщите мне.

Я снова побежал к демо, и здесь идут журналы. введите описание изображения здесь

Таким образом, он работает отлично и более 3 минут. Также эта 3-минутная логика правильная, но при запуске uibackgroundtask она не должна позволять ей убивать эту задачу таймера.

Отредактированная часть: – bgTask = [app beginBackgroundTaskWithExpirationHandler: ^ {[app endBackgroundTask: bgTask]; // Удалите эту строку, и она будет работать до тех пор, пока будет запущен таймер, и когда приложение будет убито, автоматически автоматически удаляются все vairbles и его области. }];

Проверьте это и сообщите мне, если это сработает или нет.

Эй, я запустил код ur, и я дошел до expirationHandler, но после выпуска отлаживаемой точки таймер работал ровно.

Выделенная часть - это когда я достиг обработчика

Нет, не выполняйте фоновые задачи с помощью NSTimer. Он не будет работать так, как вы могли бы ожидать. Вы должны использовать API-интерфейсы фоновой выборки, предоставляемые только Apple. Вы можете установить продолжительность, в которой вы хотите, чтобы он был вызван в этом API. Хотя обычно не рекомендуется устанавливать длительность звонка, который вы хотите сделать. Взгляните на эту документацию по программированию на яблочном фоне

Кроме того, чтобы вы начали быстро, вы можете следовать этому учебнику Appcoda

Это нормальное поведение.

После iOS7 вы получите ровно 3 минуты фонового времени. До этого было 10 минут, если я правильно помню. Чтобы расширить это, ваше приложение должно использовать некоторые специальные сервисы, такие как местоположение, аудио или Bluetooth, которые сохранят его «живым» в фоновом режиме.

Кроме того, даже если вы используете одну из этих служб, на вашем устройстве для приложения должна быть включена настройка «Обновление фонового приложения».

См. Этот ответ для получения дополнительной информации или части выполнения фона документа.

Это сработало для меня, поэтому я добавляю его в StackOverflow для любых будущих искателей ответов.

Добавьте следующий метод утилиты, который нужно вызвать до запуска таймера. Когда мы вызываем приложение AppDelegate.RestartBackgroundTimer (), оно гарантирует, что ваше приложение останется активным – даже если оно находится в фоновом режиме или если экран заблокирован. Однако это будет гарантировать, что в течение 3 минут (как вы упомянули):

 class AppDelegate: UIResponder, UIApplicationDelegate { static var backgroundTaskIdentifier: UIBackgroundTaskIdentifier? = nil; static func RestartBackgroundTimer() { if (AppDelegate.backgroundTaskIdentifier != nil) { print("RestartBackgroundTimer: Ended existing background task"); UIApplication.sharedApplication().endBackgroundTask(AppDelegate.backgroundTaskIdentifier!); AppDelegate.backgroundTaskIdentifier = nil; } print("RestartBackgroundTimer: Started new background task"); AppDelegate.backgroundTaskIdentifier = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({ UIApplication.sharedApplication().endBackgroundTask(AppDelegate.backgroundTaskIdentifier!); AppDelegate.backgroundTaskIdentifier = nil; }) } } 

Кроме того, при запуске приложения убедитесь в следующем запуске. Это обеспечит воспроизведение звука, даже если приложение находится в фоновом режиме (и пока вы на нем, также убедитесь, что ваш Info.plist содержит «Требуемые фоновые режимы» и что «Приложение воспроизводит аудио или передает аудио / видео с помощью AirPlay «aka« audio »находится в его коллекции):

 import AVFoundation; // setup audio to not stop in background or when silent do { try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback); try AVAudioSession.sharedInstance().setActive(true); } catch { } 

Теперь, в классе, для которого таймер должен работать более 3 минут (если в фоновом режиме), вам необходимо воспроизвести звук, когда осталось только 30 секунд фонового времени. Это восстановит оставшееся время фона до 3 минут (просто создайте «Silent.mp3», например AudaCity, и перетащите его в проект XCode).

Чтобы все это сделать, сделайте следующее:

 import AVFoundation class MyViewController : UIViewController { var timer : NSTimer!; override func viewDidLoad() { // ensure we get background time & start timer AppDelegate.RestartBackgroundTimer(); self.timer = NSTimer.scheduledTimerWithTimeInterval(0.25, target: self, selector: #selector(MyViewController.timerInterval), userInfo: nil, repeats: true); } func timerInterval() { var bgTimeRemaining = UIApplication.sharedApplication().backgroundTimeRemaining; print("Timer... " + NSDateComponentsFormatter().stringFromTimeInterval(bgTimeRemaining)!); if NSInteger(bgTimeRemaining) < 30 { // 30 seconds of background time remaining, play silent sound! do { var audioPlayer = try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Silent", ofType: "mp3")!)); audioPlayer.prepareToPlay(); audioPlayer.play(); } catch { } } } } 
Interesting Posts

Проверка соответствия AFNetworking

Больше проблем с синхронизацией ядра iCloud

Могу ли я использовать UIRefreshControl в UIScrollView?

Как получить текущее время воспроизведения и общее время воспроизведения в AVPlayer?

Удаление исходных данных xcdatamodel файлов

Как получить уведомление о переменной Bool, заданной в наборе параметров, когда приложение iphone находится в фоновом режиме?

Xcode: ошибка: файл модуля был создан для несовместимого целевого armv7-apple-ios8.0 (Alamofire & Cocoapods)

(iOS) Несколько уведомлений через locationManager: didExitRegion: при выходе из региона

Генерация подписи iOS OAuth?

где пример iOS Bluetooth LE периферийногоManager didReceiveWriteRequests

Может ли чистая проверка подлинности покупки на устройстве в режиме реального времени с iOS6?

Синхронизация по времени для приложения iOS

Реализация основных данных в Swift 3 с несколькими контроллерами представлений

Как последовательно останавливать AVAudioSession после AVSpeechUtterance

царство какао: предикат для выбора предметов, не связанных

Давайте будем гением компьютера.