iOS应用进入后台后计时器和位置更新停止问题的解决办法

所属分类: 软件编程 / IOS 阅读数: 1569
收藏 0 赞 0 分享

由于iOS系统为“伪后台”运行模式,当按下HOME键时,如程序不做任何操作,应用会有5秒的执行缓冲时间,随机程序被挂起,所有任务终端,包括计时器和位置更新等操作,但程序打开后台模式开关后,部分任务可以再后台执行,如音频,定位,蓝牙,下载,VOIP,即便如此,程序的后台运行最多可以延长594秒(大概是10分钟)。不幸的是,程序在声明后台模式后很有可能在app上架时被拒。基于此,我研究出了不用申明后台模式就能让计时器和定位在app进入前台时继续运行的方法。

  实现原理如下:

  利用iOS的通知机制,在程序进入后台和再次回到前台时发送通知,并记录进入后台的当前时间和再次回到前台的当前时间,算出两者的时间间隔,在程序任何需要的地方添加通知监听者,在监听方法中执行代码块,代码块内参数为通知对象和计算出的时间间隔。以计时器为例,程序再进入后台后,计时器停止运行,此时运用上述方法,在程序再次回到前台时执行代码块中内容,将程序进入后台时计时器的当前时间间隔加上代码块的时间间隔参数就能使计时器准确无误地计时。废话不多说,上代码:

在AppDelegate.m实现文件中:

- (void)applicationDidEnterBackground:(UIApplication *)application {
  // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
  // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
  [[NSNotificationCenter defaultCenter]postNotificationName:UIApplicationDidEnterBackgroundNotification object:nil];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
  // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
  [[NSNotificationCenter defaultCenter]postNotificationName:UIApplicationWillEnterForegroundNotification object:nil];
}

代码说明:程序进入后台后,利用系统通知机制通知程序进入后台和再次回到前台,监听对象为所有对象。

之后定义一个处理程序进入后台的类YTHandlerEnterBackground

//
// YTHandlerEnterBackground.h
// 分时租赁
//
// Created by 柯其谱 on 17/2/24.
// Copyright © 2017年 柯其谱. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
/** 进入后台block typedef */
typedef void(^YTHandlerEnterBackgroundBlock)(NSNotification * _Nonnull note, NSTimeInterval stayBackgroundTime);
/** 处理进入后台并计算留在后台时间间隔类 */
@interface YTHandlerEnterBackground : NSObject
/** 添加观察者并处理后台 */
+ (void)addObserverUsingBlock:(nullable YTHandlerEnterBackgroundBlock)block;
/** 移除后台观察者 */
+ (void)removeNotificationObserver:(nullable id)observer;
@end

在YTHandlerEnterBackground.m实现文件中:

//
// YTHandlerEnterBackground.m
// 分时租赁
//
// Created by 柯其谱 on 17/2/24.
// Copyright © 2017年 柯其谱. All rights reserved.
//
#import "YTHandlerEnterBackground.h"
@implementation YTHandlerEnterBackground
+ (void)addObserverUsingBlock:(YTHandlerEnterBackgroundBlock)block {
  __block CFAbsoluteTime enterBackgroundTime;
  [[NSNotificationCenter defaultCenter]addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
    if (![note.object isKindOfClass:[UIApplication class]]) {
      enterBackgroundTime = CFAbsoluteTimeGetCurrent();
    }
  }];
  __block CFAbsoluteTime enterForegroundTime;
  [[NSNotificationCenter defaultCenter]addObserverForName:UIApplicationWillEnterForegroundNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
    if (![note.object isKindOfClass:[UIApplication class]]) {
      enterForegroundTime = CFAbsoluteTimeGetCurrent();
      CFAbsoluteTime timeInterval = enterForegroundTime-enterBackgroundTime;
      block? block(note, timeInterval): nil;
    }
  }];
}
+ (void)removeNotificationObserver:(id)observer {
  if (!observer) {
    return;
  }
  [[NSNotificationCenter defaultCenter]removeObserver:observer name:UIApplicationDidEnterBackgroundNotification object:nil];
  [[NSNotificationCenter defaultCenter]removeObserver:observer name:UIApplicationWillEnterForegroundNotification object:nil];
}
@end

该类实现了用来添加通知监听者并处理后台和移除通知监听者的方法,需要注意的是,在addObserverUsingBlock方法中,必须有if (![note.object isKindOfClass:[UIApplication class]])的判断,否则addObserverForName方法中的代码块会执行多次,此代码执行了两次。addObserverUsingBlock方法是在viewWillAppear方法中调用添加通知监听者,在viewWillDisappear方法中调用移除通知监听者。

例如,在使用了计时器NSTimer控制器中:

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  [YTHandlerEnterBackground addObserverUsingBlock:^(NSNotification * _Nonnull note, NSTimeInterval stayBackgroundTime) {
    self.rentTimerInterval = self.rentTimerInterval-stayBackgroundTime;
  }];
}
- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  [self.timer invalidate];
  [YTHandlerEnterBackground removeNotificationObserver:self];
}

我定义了一个倒计时5分钟的计时器对象timer属性,并定义了一个计时器当前倒计时时间间隔rentTimerInterval属性,在添加通知监听者代码块中,rentTimerInterval等于进入后台时的倒计时时间间隔减去程序停留在后台的时间间隔,当计时器再次回到前台时,计时器此时的时间间隔是持续的。虽然计时器并未在后台持续运行,但是使用了此方法,同样实现了计时器的正确即时。

同样的,当程序存在位置更新功能时,当程序进入后台,位置服务对象会自动停止更新,此时的作法依然是调用上述两个处理进入后台的方法,使得程序进入后台后,再次开始定位:

在需要位置更新的类中:

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  self.locService.delegate = self;
  [self.locService startUserLocationService];
  //进入后台再进入前台重新开始定位
  [YTHandlerEnterBackground addObserverUsingBlock:^(NSNotification * _Nonnull note, NSTimeInterval stayBackgroundTime) {
    [self.locService startUserLocationService];
  }];
}
- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  //停止定位
  self.locService.delegate = nil;
  [self.locService stopUserLocationService];
  //移除后台监听
  [YTHandlerEnterBackground removeNotificationObserver:self];
}

此处使用的是百度地图SDK

利用这种方法,像是计时器和位置更新等需要在后台运行的任务都可以实现相应的需求,只是麻烦的是,在任何需要的类中都要调用这两种方法,你可以根据自己的需求,在程序进入后台和再次回到前台时添加别的参数(通知对象参数是必须的),例如保存进入后台前的操作等等。或是定义不同的添加通知监听者的方法以实现不同的需求。

以上所述是小编给大家介绍的iOS应用进入后台后计时器和位置更新停止问题的解决办法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

更多精彩内容其他人还在看

iOS开发笔记--详解UILabel的相关属性设置

这篇文章主要介绍了iOS开发笔记--详解UILabel的相关属性设置,对初学者具有一定的参考价值,有需要的可以了解一下。
收藏 0 赞 0 分享

iOS中获取系统相册中的图片实例

这篇文章主要介绍了iOS中获取系统相册中的图片实例,具有一定的参考价值没有需要的朋友可以了解一下。
收藏 0 赞 0 分享

iOS 检测网络状态的两种方法

一般有Reachability和AFNetworking监测两种方式,都是第三方的框架,下文逐一详细给大家讲解,感兴趣的朋友一起看看吧
收藏 0 赞 0 分享

IOS 性能优化中离屏渲染

本文主要介绍了IOS 性能优化中离屏渲染的资料,提供了几种方法讲解了优化,有需要的小伙伴可以参考下
收藏 0 赞 0 分享

iOS获取当前设备型号等信息(全)包含iPhone7和iPhone7P

这篇文章主要介绍了iOS获取当前设备型号设备信息的总结包含iPhone7和iPhone7P,包括ios7之前之后的获取方式,本文接的非常详细,具有参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

iOS实现爆炸的粒子效果示例代码

之前在网上看到了一个Android实现的爆炸效果,感觉非常不错,所以自己尝试用iOS来实现下效果,现在将实现的过程、原理以及遇到的问题分享给大家,有需要的朋友们可以参考借鉴,下面来一起看看吧。
收藏 0 赞 0 分享

iOS毕业设计之天气预报App

这篇文章主要为大家详细介绍了iOS毕业设计之天气预报App,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

iOS轻点、触摸和手势代码开发

这篇文章主要为大家详细介绍了iOS轻点、触摸和手势代码开发,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

iOS 实现多代理的方法及实例代码

这篇文章主要介绍了iOS 实现多代理的方法及实例代码的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

iOS文字渐变色效果的实现方法

在大家日常开发iOS的过程中,可能会遇到要实现文字渐变色的效果,这篇文章文章通过示例代码和详细的步骤介绍了如何利用iOS实现文字渐变色的效果,实现后的很不错,感兴趣的朋友们下面来一起看看吧。
收藏 0 赞 0 分享
查看更多