iOS系统在后台执行程序时,有严格的限制,为了更好地管理资源和电池寿命,iOS会限制应用程序在后台的运行时间。然而,iOS提供了一些特定的策略和技术,使得应用程序可以在特定场景下保持后台运行(即“后台保活”)。以下是iOS中几种常见的后台保活方案,并附上示例代码:

一、后台任务

利用beginBackgroundTaskendBackgroundTask来执行后台任务。后台任务将在应用程序进入后台时仍能保持有限的时间执行任务。

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (assign, nonatomic) UIBackgroundTaskIdentifier bgTask; @end @implementation AppDelegate - (void)applicationDidEnterBackground:(UIApplication *)application {
self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
}]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 在这里执行你的后台任务
for (int i = 0; i < 100; i++) {
NSLog(@"Background task running %d", i);
[NSThread sleepForTimeInterval:1];
} [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
});
} @end

二、使用Background Fetch

利用Background Fetch,系统会间歇性地唤醒应用程序,以便它可以执行任务或获取数据。需要在Xcode的“Capabilities”中开启Background Modes,并勾选“Background fetch”。

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return YES;
} - (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// 在这里执行你的后台数据获取任务
NSLog(@"Background fetch started"); // 模拟数据获取
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"Background fetch completed");
completionHandler(UIBackgroundFetchResultNewData);
});
} @end

三、使用远程通知(Silent Push Notification)

利用远程通知,在接收到通知时,系统会唤醒应用程序执行指定的任务。需要开启Remote notifications,在Application Capabilities中勾选“Remote notifications”。

#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h> @interface AppDelegate : UIResponder <UIApplicationDelegate, UNUserNotificationCenterDelegate> @property (strong, nonatomic) UIWindow *window; @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
}];
return YES;
} - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// 在这里处理收到的远程通知
NSLog(@"Received remote notification"); // 模拟处理任务
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"Handled remote notification");
completionHandler(UIBackgroundFetchResultNewData);
});
} @end

四、使用特定的后台模式(Background Modes)

iOS提供了一些特定的后台模式,允许程序在后台持续运行。常见的后台模式包括:

  • Audio: 允许应用程序在后台播放音频。
  • Location: 允许应用程序在后台持续获取位置更新。
  • VoIP: 允许应用程序在后台侦听VoIP事件。
  • Bluetooth: 允许应用程序与蓝牙设备通信。

1. Audio后台模式

需要在Xcode的“Capabilities”中开启Background Modes,并勾选“Audio, AirPlay, and Picture in Picture”。

#import <AVFoundation/AVFoundation.h>

@interface AppDelegate ()

@property (nonatomic, strong) AVAudioPlayer *audioPlayer;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSError *error = nil;
NSURL *audioURL = [[NSBundle mainBundle] URLForResource:@"audioFileName" withExtension:@"mp3"];
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error];
[self.audioPlayer prepareToPlay]; AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
[audioSession setActive:YES error:&error]; return YES;
} - (void)applicationDidEnterBackground:(UIApplication *)application {
[self.audioPlayer play];
} @end

2. Location后台模式

需要在Xcode的“Capabilities”中开启Background Modes,并勾选“Location updates”。

#import <CoreLocation/CoreLocation.h>

@interface AppDelegate () <CLLocationManagerDelegate>

@property (nonatomic, strong) CLLocationManager *locationManager;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager requestAlwaysAuthorization];
return YES;
} - (void)applicationDidEnterBackground:(UIApplication *)application {
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
} - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
CLLocation *location = [locations lastObject];
NSLog(@"Background location: %@", location);
} @end

五、使用后台URLSession

使用NSURLSession来执行后台下载和上传任务。需要在后台配置中开启Background Modes,并勾选“Background fetch”和“Remote notifications”。

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate, NSURLSessionDelegate, NSURLSessionDownloadDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic, strong) NSURLSession *backgroundSession; @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.example.background"];
self.backgroundSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
return YES;
} - (void)applicationDidEnterBackground:(UIApplication *)application {
NSURL *url = [NSURL URLWithString:@"http://example.com/largefile.zip"];
NSURLSessionDownloadTask *downloadTask = [self.backgroundSession downloadTaskWithURL:url];
[downloadTask resume];
} - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
NSLog(@"Download completed: %@", location);
// 处理下载结果,比如保存文件
} @end

通过上述几种方案,我们可以在iOS应用程序中实现各种场景下的后台保活。每种方案都有其适用的场景和限制,开发者需要根据应用的实际需求和系统提供的特性,选择合适的后台保活方案。

iOS开发基础102-后台保活方案的更多相关文章

  1. 《推送开发全面盘点当前Android后台保活方案的真实运行效果》

        登录 立即注册 TCP/IP详解 资讯 动态 社区 技术精选 首页   即时通讯网›专项技术区›推送开发全面盘点当前Android后台保活方案的真实运行效果(截止2 ...   帖子 打赏 分 ...

  2. 全面盘点当前Android后台保活方案的真实运行效果(截止2019年前)

    本文原作者“minminaya”,作者网站:minminaya.cn,为了提升文章品质,即时通讯网对内容作了幅修订和改动,感谢原作者. 1.引言 对于IM应用和消息推送服务的开发者来说,在Androi ...

  3. IOS开发基础环境搭建

    一.目的 本文的目的是windows下IOS开发基础环境搭建做了对应的介绍,大家可根据文档步骤进行mac环境部署: 二.安装虚拟机 下载虚拟机安装文件绿色版,点击如下文件安装 获取安装包:       ...

  4. 【1】windows下IOS开发基础环境搭建

    一.目的 本文的目的是windows下IOS开发基础环境搭建做了对应的介绍,大家可根据文档步骤进行mac环境部署: 二.安装虚拟机 下载虚拟机安装文件绿色版,点击如下文件安装 获取安装包:       ...

  5. IOS开发基础知识碎片-导航

    1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...

  6. iOS开发——总结篇&IOS开发基础知识

    IOS开发基础知识 1:Objective-C语法之动态类型(isKindOfClass, isMemberOfClass,id) 对象在运行时获取其类型的能力称为内省.内省可以有多种方法实现. 判断 ...

  7. iOS开发基础-九宫格坐标(6)

    继续对iOS开发基础-九宫格坐标(5)中的代码进行优化. 优化思路:把字典转模型部分的数据处理操作也拿到模型类中去实现,即将 ViewController 类实现中 apps 方法搬到 WJQAppI ...

  8. iOS开发基础-九宫格坐标(5)

    继续在iOS开发基础-九宫格坐标(4)的基础上进行优化. 一.改进思路 1)iOS开发基础-九宫格坐标(4)中 viewDidLoad 方法中的第21.22行对控件属性的设置能否拿到视图类 WJQAp ...

  9. iOS开发基础-九宫格坐标(4)

    对iOS开发基础-九宫格坐标(3)的代码进行进一步优化. 新建一个 UIView 的子类,并命名为 WJQAppView ,将 appxib.xib 中的 UIView 对象与新建的视图类进行关联. ...

  10. iOS开发基础-九宫格坐标(3)之Xib

    延续iOS开发基础-九宫格坐标(2)的内容,对其进行部分修改. 本部分采用 Xib 文件来创建用于显示图片的 UIView 对象. 一.简单介绍  Xib 和 storyboard 的比较: 1) X ...

随机推荐

  1. Springboot 项目集成 PageOffice V6 最简单代码

    本文描述了PageOffice产品在Springboot项目中如何集成调用.(本示例使用了Thymeleaf模板引擎) 新建Springboot项目:pageoffice6-springboot2-s ...

  2. SpringBoot自定义注解失效原因(2022-10-3)

    长话短说,我负责的是一个多模块项目,接手的时候没有注意 @ComponentScan 注解的扫描范围,所以打包的时候,没有扫到我新加包. 所以,重点检查下 @ComponentScan 注解的范围

  3. zabbix笔记_007 zabbix 分布式架构

    1. zabbix 分布式架构[服务器数量较大的场景下使用] 现有架构: agent --> zabbix server proxy架构: agent --> zabbix proxy - ...

  4. insert into select [SQL]

    insert into `d_mx_think`.`su_article` (id,catid,title,url) select id,catid,title,url from d_mx_phpcm ...

  5. github加速与添加ssh密钥

    part1-github加速 此处推荐Fetch GitHub Hosts,文章的中间位置有手动添加dns的内容,十分完备,此处不赘述.不知道是不是我家网络抽风,总是得代理才能进githubQAQ难受 ...

  6. Advanced .Net Debugging 9:平台互用性

    一.介绍 这是我的<Advanced .Net Debugging>这个系列的第九篇文章.这篇文章的内容是原书的第二部分的[调试实战]的第七章[互用性].互用性包含两个方面,第一个方面就是 ...

  7. CF1815

    CF1815 Div. 1 确实难,Virtual Contest 上只完成了两道题,想出来了三道题. A. Ian and Array Sorting 秒切题--考虑将前 \(n - 1\) 个数变 ...

  8. kettle从入门到精通 第二十九课 job 循环 检验字段的值

    1.平常我们在用kettle设计job的时候,会用到循环来处理一些业务逻辑,比如循环检测某个表中的数据条数等.这个时候就会用到一个特别重要的步骤:检验字段的值. 下图是一个的通过初始化DNOE变量为f ...

  9. Windows Server 2016 离线安装.NET Framework 3.5

    Windows Server 2016 离线安装.NET Framework 3.5 1.双击Windows Server 2016的ISO,会自动挂载,比如F盘. 2.右键开始菜单- 命令提示符(管 ...

  10. window.onload()函数和jQuery中的document.ready()有什么区别?

    a.执行时间:window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行.$(document).ready()是DOM结构绘制      完毕后就执行,不必等到加载完毕.$(doc ...