iOS 前台重启应用和清除角标的问题

问:应用启动时是否会执行 - (void)applicationWillEnterForeground:(UIApplication *)application ?
答:不会 ? 你确定?那看一哈下面的情况。示例Github地址

前台时重启应用调用了applicationWillEnterForeground:

已知条件:

   应用在退到后台时,会给应用加上一层毛玻璃效果,防止iOS系统自动对应用当前界面进行截屏处理时获取到用户的某些隐私,提高安全性;同时也会在退到后台时,重置应用的消息角标。


//当应用启动载入完成后执行,也就是系统启动屏加载完成后执行
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    NSLog(@" 应用启动完成 ");
    //延长系统启动屏展示的时长
    [NSThread sleepForTimeInterval:2];
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
    
    //注册通知
    UNUserNotificationCenter * center  = [UNUserNotificationCenter currentNotificationCenter];
    //设置代理,用于检测点击方法
    center.delegate = self;
    //申请权限
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound + UNAuthorizationOptionBadge + UNAuthorizationOptionCarPlay) completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if (granted) {
            NSLog(@"用户同意开启通知");
        }
    }];
    return YES;
}

//当应用即将进入非活动状态时执行
- (void)applicationWillResignActive:(UIApplication *)application {
    NSLog(@" 即将进入非活动状态 ");
}

//当应用进入后台时执行  或者应用在前台时被强制关闭时执行
- (void)applicationDidEnterBackground:(UIApplication *)application {
    //给处于后台的应用添加毛玻璃效果
    if (_effectView == nil) {
        UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
        _effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
        _effectView.frame = CGRectMake(0, 0, self.window.frame.size.width, self.window.frame.size.height);
    }
    [self.window addSubview:_effectView];
    
    // 实现如下代码,才能使程序处于后台时被杀死后调用applicationWillTerminate:方法
     [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(){}];
  
    //重置应用的角标
    [self resetApplicationIconBadgeNumber];
    NSLog(@" 进入后台 ");
}

//当应用即将从后台进入前台时执行,重新启动应用时并不执行,除了此demo演示的特殊情况
- (void)applicationWillEnterForeground:(UIApplication *)application {
  
    if (_effectView != nil) {
        [_effectView removeFromSuperview];
        _effectView = nil;
    }
    
    //弹窗
//   SL_ULog(@"执行了 applicationWillEnterForeground ");
    NSLog(@" 即将从后台进入前台 ");
}

//当应用进入活动状态时执行
- (void)applicationDidBecomeActive:(UIApplication *)application {
    if (_effectView != nil) {
        [_effectView removeFromSuperview];
        _effectView = nil;
    }
    NSLog(@" 进入活动状态 ");
}

//应用被杀死时调用
- (void)applicationWillTerminate:(UIApplication *)application {
    NSLog(@" 应用被杀死了 ");
}

#pragma mark - iOS10 收到通知(本地和远端) UNUserNotificationCenterDelegate

//当APP处于前台的时候收到通知的事件
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{
    // 系统要求执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置
    completionHandler(UNNotificationPresentationOptionBadge|
                      UNNotificationPresentationOptionSound|
                      UNNotificationPresentationOptionAlert);
}

//这个方法是为了清除应用的角标,同时又不清除之前发送的通知内容
- (void)resetApplicationIconBadgeNumber {
 //使用这个方法清除角标,如果置为0的话会把之前收到的通知内容都清空;置为-1的话,不但能保留以前的通知内容,还有角标消失动画,iOS10之前这样设置是没有作用的 ,iOS10之后才有效果 。
    [UIApplication sharedApplication].applicationIconBadgeNumber = -1;
    
//这个发送本地通知的操作是为了解决在iOS10之前清除角标的同时可以保留通知内容的问题
   //这个进入后台时清除角标的操作会造成:应用在前台时被强制关闭后,立马重启应用后会调用方法applicationWillEnterForeground:,正常情况下重新启动应用时并不执行它.
//    UILocalNotification *clearEpisodeNotification = [[UILocalNotification alloc] init];
//    clearEpisodeNotification.applicationIconBadgeNumber = -1;
//    [[UIApplication sharedApplication] scheduleLocalNotification:clearEpisodeNotification];
}

问题描述:

   当应用在前台时,手动强制重启应用后,发现没有正常的加载启动屏,加载的启动屏是退入后台时的应用截屏。

前台时重启应用出现的问题展示

调试分析

   经过不断调试之后,发现:在前台时重启应用后,调用 application: didFinishLaunchingWithOptions: 方法之后,还调用了applicationWillEnterForeground: ???? “这操作不合理呀!应用启动时应该不会执行 applicationWillEnterForeground 方法呀!” 如下示意图,我加了个弹窗验证:

前台时重启应用调用了applicationWillEnterForeground:

   为什么在前台时重启应用会执行 applicationWillEnterForeground ?通过删除排除法,找到了导致此问题的代码,如下,这段代码是退入后台时清除角标的操作。如果不在应用退入后台时执行下面的清除角标操作,就是正常的。


//当应用进入后台时执行  或者应用在前台时被强制关闭时执行
- (void)applicationDidEnterBackground:(UIApplication *)application {
//这个发送本地通知的操作是为了解决在iOS10之前清除角标的同时可以保留通知内容的问题
 //这个清除角标的操作只在进入后台时执行才会造成:应用在前台时被强制关闭后,立马重启应用后会调用方法applicationWillEnterForeground:,正常情况下重新启动应用时并不执行它;
    UILocalNotification *clearEpisodeNotification = [[UILocalNotification alloc] init];
    clearEpisodeNotification.applicationIconBadgeNumber = -1;
    [[UIApplication sharedApplication] scheduleLocalNotification:clearEpisodeNotification];
}

   这时有人肯定会疑惑为啥不用[UIApplication sharedApplication].applicationIconBadgeNumber = 0 ?
   因为把应用角标值置为0的话会把之前收到的通知栏内的通知内容都清空,这样显然是不合理的;如果置为-1的话,不但能保留以前的通知内容,还有角标消失动画,iOS10之前这样设置是没有作用的 ,iOS10之后才有效果 ;所以iOS10之前只能通过上述代码来实现。

解决问题

   方案一 : 把上述清除角标的代码放在应用进入前台时执行的方法 applicationDidBecomeActive: 里面,这样的话就是看不到角标消失的过程。
   方案二:通过 [UIApplication sharedApplication].applicationIconBadgeNumber = -1 来清除角标。


- (void)applicationDidEnterBackground:(UIApplication *)application {
   //使用这个方法清除角标,如果置为0的话会把之前收到的通知内容都清空;置为-1的话,不但能保留以前的通知内容,还有角标消失动画,iOS10之前这样设置是没有作用的 ,iOS10之后才有效果 。
    [UIApplication sharedApplication].applicationIconBadgeNumber = -1;
}

问题解决后

虽然问题解决了,但是为什么 调试分析 步骤中的问题代码会导致在前台时重启应用会执行 applicationWillEnterForeground:? 是系统的Bug ? 如果小伙伴有谁知道的话,欢迎底部留言交流 👏👏👏

如果需要跟我交流的话:
※ Github: https://github.com/wsl2ls
※ 简书:https://www.jianshu.com/u/e15d1f644bea
※ 微信公众号:iOS2679114653
※ QQ:1685527540

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容