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 关于后台持续运行 - 简书

相关推荐
若水无华18 小时前
fiddler 配置ios手机代理调试
ios·智能手机·fiddler
Aress"19 小时前
【ios越狱包安装失败?uniapp导出ipa文件如何安装到苹果手机】苹果IOS直接安装IPA文件
ios·uni-app·ipa安装
Jouzzy1 天前
【iOS安全】Dopamine越狱 iPhone X iOS 16.6 (20G75) | 解决Jailbreak failed with error
安全·ios·iphone
瓜子三百克1 天前
采用sherpa-onnx 实现 ios语音唤起的调研
macos·ios·cocoa
左钦杨1 天前
IOS CSS3 right transformX 动画卡顿 回弹
前端·ios·css3
努力成为包租婆1 天前
SDK does not contain ‘libarclite‘ at the path
ios
安和昂2 天前
【iOS】Tagged Pointer
macos·ios·cocoa
I烟雨云渊T2 天前
iOS 阅后即焚功能的实现
macos·ios·cocoa
struggle20252 天前
适用于 iOS 的 开源Ultralytics YOLO:应用程序和 Swift 软件包,用于在您自己的 iOS 应用程序中运行 YOLO
yolo·ios·开源·app·swift
Unlimitedz2 天前
iOS视频编码详细步骤(视频编码器,基于 VideoToolbox,支持硬件编码 H264/H265)
ios·音视频