iOS 后台运行

iOS后台行,一般有两种方式:

1.UIBackgroundTaskIdentifier后台任务标记时,

2.设置后台运行模式,需要有voip,location功能的才行。不然app上线审核肯定是过不了的。

下面是我学习后台运行的尝试过程。

一.首先创建一个项目功程用来测试后台运行情况。这里我参照别人的一篇文章,在后台增加角标值。

直接上代码。

objectivec 复制代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
        //注册推送,设置角标也需要 不然角标显示不了
    if(version >= 10.0)
    {
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (error) { NSLog(@"request authorization error: %@", error); }
        }];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
}

//进入前台,结速后台任务
- (void) applicationWillEnterForeground:(UIApplication *)application
{
    if(_badgeTimer)
    {
        dispatch_source_cancel(_badgeTimer);
        _badgeTimer = nil;
    }
}


//进入后台,开始后台任务,启动定时器每隔一秒给角标加一
- (void)applicationDidEnterBackground:(UIApplication *)application {
    
    //方法一
    [self stratBadgeNumberCount];
}

- (void)stratBadgeNumberCount{
    [UIApplication sharedApplication].applicationIconBadgeNumber = 0;

    if(_badgeTimer)
    {
        dispatch_source_cancel(_badgeTimer);
        _badgeTimer = nil;
    }
    
    //定时器增加角标
    _badgeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    dispatch_source_set_timer(_badgeTimer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(_badgeTimer, ^{
        
        [UIApplication sharedApplication].applicationIconBadgeNumber++;
    
    });
    dispatch_resume(_badgeTimer);
}

程序运行后,返回后台。程序的角标加到1就不再增加了。 注意如果设置了后台运行模式

voip,locationt等会一直增加的。但是你app里没有这些功能的话app store审核肯定是过不了的。如下图

二.尝试使用UIBackgroundTaskIdentifier后台任务标记时

1) Background Task仅用于执行短时间的任务,APP切换到后台后,可以通过beginBackgroundTaskWithExpirationHandler申请一段时间的后台时间,你的任务应该在这段时间内执行完成,否则会被系统杀死。

2) Background Task的持续时间并不是一个固定值,在不同性能的设备上差别巨大。在iPhone 10上为30秒,这个是我自己测试的,据说,在高性能的设备上则达到180秒。最长持续时间似乎还和当前的资源占用情况有关。

3)beginBackgroundTask和endBackgroundTask必须成对出现如果使用全局的UIBackgroundTaskIdentifier记录后台任务,需要注意每次执行beginBackgroundTask都会生成新的UIBackgroundTaskIdentifier。旧的UIBackgroundTaskIdentifier会被覆盖,则上一个UIBackgroundTaskIdentifier就没有机会执行endBackgroundTask。此时会出现beginBackgroundTask和endBackgroundTask不配对的情况,可能会被系统杀死。

objectivec 复制代码
//进入后台,开始后台任务,启动定时器每隔一秒给角标加一
- (void)applicationDidEnterBackground:(UIApplication *)application {
    
    //方法一
    [self stratBadgeNumberCount];
    [self startBgTask];
}

#pragma mark - 方法一
//开启后台任务
- (void)startBgTask{
    UIApplication *application = [UIApplication sharedApplication];

    if(_bgTask != UIBackgroundTaskInvalid)
    {
        [self endBackgroundTask];
    }

    _bgTask = [application beginBackgroundTaskWithExpirationHandler:^{

        NSLog(@"%f",application.backgroundTimeRemaining);

        //在这个地方重新开启后台任务不启作用
        //[weakSelf startBgTask];
        
        [self endBackgroundTask];
    }];
}

//结束后台任务
- (void) endBackgroundTask
{
    UIApplication *application = [UIApplication sharedApplication];
    [application endBackgroundTask:_bgTask];

    _bgTask = UIBackgroundTaskInvalid;
}

使用UIBackgroundTaskIdentifier后台可以延迟30秒左右就被挂启了。测试结果是角标加到31就不再继续加了。据说以前ios可以延迟180秒。没测过。

三.Background Mode

启用Background Mode后(音频播放、后台定位、VoIP等),是没有后台时间限制的。

objectivec 复制代码
//进入前台,结速后台任务
- (void) applicationWillEnterForeground:(UIApplication *)application
{
//    [self endBackgroundTask];
    if(_badgeTimer)
    {
        dispatch_source_cancel(_badgeTimer);
        _badgeTimer = nil;
    }
}

//进入后台,开始后台任务,启动定时器每隔一秒给角标加一
- (void)applicationDidEnterBackground:(UIApplication *)application {
    
    [self stratBadgeNumberCount];

    [self.player play];
    
    //用AVAudioPlayer或CLLocationManager其一就可以
    //方法三 (还没验证)
//    self.appleLocationManager = [[CLLocationManager alloc] init];
//    self.appleLocationManager.allowsBackgroundLocationUpdates = YES;
//    self.appleLocationManager.desiredAccuracy = kCLLocationAccuracyBest;
//    self.appleLocationManager.delegate = self;
//    [self.appleLocationManager requestAlwaysAuthorization];
//    [self.appleLocationManager startUpdatingLocation];

}

- (void)stratBadgeNumberCount{
    [UIApplication sharedApplication].applicationIconBadgeNumber = 0;

    if(_badgeTimer)
    {
        dispatch_source_cancel(_badgeTimer);
        _badgeTimer = nil;
    }
    
    //定时器增加角标
    _badgeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    dispatch_source_set_timer(_badgeTimer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(_badgeTimer, ^{
        
        [UIApplication sharedApplication].applicationIconBadgeNumber++;
    
    });
    dispatch_resume(_badgeTimer);
}

#pragma mark
- (AVAudioPlayer *)player{
    if (!_player){
        NSURL *url=[[NSBundle mainBundle]URLForResource:@"work5.mp3" withExtension:nil];
        _player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
        [_player prepareToPlay];
        //一直循环播放
        _player.numberOfLoops = -1;
        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session setCategory:AVAudioSessionCategoryPlayback error:nil];

        [session setActive:YES error:nil];
    }
    return _player;
}



#pragma mark
/** 苹果_用户位置更新后,会调用此函数 */
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
    [self.appleLocationManager stopUpdatingLocation];
    self.appleLocationManager.delegate = nil;

    [UIApplication sharedApplication].applicationIconBadgeNumber++;
    NSLog(@"success");
}

/** 苹果_定位失败后,会调用此函数 */
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
    [self.appleLocationManager stopUpdatingLocation];
    self.appleLocationManager.delegate = nil;
    NSLog(@"error");
}

同时要加上后台运行的能力

参考:iOS 关于后台持续运行 - 简书

相关推荐
胖虎116 小时前
SwiftUI 页面作为一级页面数据被重置问题分析
ios·swiftui·swift·state·observedobject·stateobject·swiftui页面生命周期
健了个平_2420 小时前
【iOS】如何在 iOS 26 的UITabBarController中使用自定义TabBar
ios·swift·wwdc
Digitally1 天前
无需 iTunes 将文件从 PC 传输到 iPhone
ios·iphone
1024小神1 天前
xcode 配置了AppIcon 但是不显示icon图标
ios·swiftui·swift
2501_915918411 天前
iOS 项目中证书管理常见的协作问题
android·ios·小程序·https·uni-app·iphone·webview
ITKEY_1 天前
iOS网页应用无地址栏无工具栏
ios
2501_915918411 天前
提升 iOS 应用安全审核通过率的一种思路,把容易被拒的点先处理
android·安全·ios·小程序·uni-app·iphone·webview
RollingPin1 天前
iOS探究使用Block方式实现一对多回调能力
ios·block·runtime·数据分发·解耦·动态绑定·一对多回调
TheNextByte11 天前
iPhone短信备份与恢复:3种最佳方法及短信备份与恢复应用
ios·iphone
2501_916008891 天前
iOS 应用发布流程中常被忽视的关键环节
android·ios·小程序·https·uni-app·iphone·webview