zoukankan      html  css  js  c++  java
  • iOS杀死程序后调用网络请求和数据库操作

    https://www.jianshu.com/p/56ae5ca5e867

     https://www.imooc.com/wenda/detail/595838

    项目中碰到一个需求,就是在退出控制器后进行埋点操作,正常情况我们在controller的delloc中执行埋点的网络请求就OK了,但是还有一种情况,如果用户杀死程序,是不会走delloc方法的。这时候需要监听杀死程序的通知,这里贴下最终代码,想看思路的请往后看。

    - (void)viewDidLoad {
        [super viewDidLoad];
        //监听通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:@"UIApplicationWillTerminateNotification" object:nil];
    }
    
    //程序被杀死
    - (void)applicationWillTerminate:(UIApplication *)application {
        //进行埋点操作
        [self uploadData];
        [NSThread sleepForTimeInterval:5];
        NSLog(@"程序被杀死");
    }
    
    
    • 一开始想着直接在监听到杀死App后直接埋点,所以在控制器中加入了如下代码:
    - (void)viewDidLoad {
        [super viewDidLoad];
        //监听通知
       [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:@"UIApplicationWillTerminateNotification" object:nil];
    }
    
    
    //程序被杀死
    - (void)applicationWillTerminate:(UIApplication *)application {
        //进行埋点操作
        [self uploadData];
        NSLog(@"程序被杀死");
    }
    
    
    • 本以为这样就大功告成了,谁知道埋点没生效,打断点发现杀死程序后网络请求并没有走完。了解到系统执行完回调applicationWillTerminate:后,在那一次主线程 runloop 结束, 系统就会杀死应用进程, 所以后续的网络请求,磁盘操作,异步代码 等等就都没执行了。在网上查找资料主要有两种方法:1.说要把这里的网络请求改成在主线程。2.另外一种方法是阻塞主线程,这里贴下该作者的代码地址https://www.jianshu.com/p/5142ebe74c6d
    • 看了这两种方法,觉得第一种方法网络请求改主线程太过麻烦,因为我这里的埋点有好几个,所以选择第二种方法,但觉得作者的做法也太麻烦了,按照思路,无非就是阻塞主线程,让埋点的网络请求走完才让主线程结束,这时候我突然灵机一动:我们启动APP进入欢迎界面一般就需要沉睡几秒才进入主界面:
    [NSThread sleepForTimeInterval:3];
    

    是否可以利用这个方法实现我们的需求?于是我在监听到App被杀死,进行埋点操作后加入上面的代码。

    - (void)viewDidLoad {
        [super viewDidLoad];
        //监听通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:@"UIApplicationWillTerminateNotification" object:nil];
    }
    
    //程序被杀死
    - (void)applicationWillTerminate:(UIApplication *)application {
        //进行埋点操作
        [self uploadData];
        [NSThread sleepForTimeInterval:5];
        NSLog(@"程序被杀死");
    }
    
    

    发现此方法确实可行,而且简单,但有个缺点就是如果网络请求慢的话,有可能埋点会失败。大家可以尝试用NSTimer阻塞,然后埋点网络请求完后invalidate。



    作者:原味丿丿咖啡Vitas
    链接:https://www.jianshu.com/p/56ae5ca5e867
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
     
     

    applicationWillTerminate什么时候调用,什么时候不调用

    慕仰0522570 2019-10-21 09:47:59

    嗨,我已经阅读了关于applicationWillTerminate被调用和未被调用的几个问题。

    我想总结一下我的理解,因为有几篇文章讲的不同。

    对于IOS(无多任务),总是在按下主页按钮时调用它。

    对于iOS 4及更高版本

    一种。按下主屏幕按钮时不会调用它(因为应用程序移至后台)

    b。当从多任务扩展坞中关闭应用程序时调用该方法,并且如果该应用程序在info.plist中禁用了突然终止标志,则不会调用它。(我设置了“应用程序应获取App Died事件”,即使在从多任务扩展坞中关闭应用程序时,也没有调用终止函数)

    基于此,我有几个问题

    设置应用程序应获取“ App Died”事件标志是一种好习惯吗?(我设置了“应用程序应获取App Died事件”,即使在从多任务扩展坞中关闭应用程序时,也没有调用终止函数)

    要么

    与“ info.plist”设置相比,注册“ UIApplicationWillTerminateNotification”更好吗?

    基本上,我只需要在应用终止时才需要做一些工作,而不必在它移到后台时才需要做。

    要么

    编辑(1):应用终止后,以下内容将发送到该应用。我怎么抓到它?

    程序收到信号:“ SIGKILL”。

    编辑(2):

    请注意:从多任务扩展坞中卸下时,它在IOS 4及更高版本中不会被调用。您可能以为是。但就我而言,事实并非如此。

    我问是否有人知道为什么?还有其他我想念的东西吗?

    另请注意,我设置了“应用程序应获取应用程序死亡事件”,即使这样它也没有被调用。

    有人面临与我类似的问题吗?

    查看完整描述

    3 回答

    ?
    慕勒3428872

    简而言之,除非您UIApplicationExitsOnSuspend在Info.plist中将其设置为YES ,否则在iOS4及更高版本中,无法保证applicationWillTerminate:会被调用。

    如文档所述:

    对于支持后台执行的应用程序,当用户退出应用程序时通常不会调用此方法,因为在这种情况下,应用程序只是移至后台。然而,这种方法可以在其中应用程序在背景中(未暂停)运行情况被调用,该系统需要终止它由于某种原因

    (强调我的。)

    如果您需要在应用退出之前执行某些操作,则需要在中执行操作applicationDidEnterBackground:。无法捕捉SIGKILL。

     反对 回复2019-10-21
     
    ?
    倚天杖

    据我所知,您的应用程序将在3种情况下死亡。

    1. 在最终用户终止后,您可以在中做某事-[UIApplication applicationWillEnterBackground:],在这种情况下,-[UIApplication applicationWillTerminate:]将不会调用。

    2. 被系统丢弃,例如内存不足,您可以在中做某事-[UIApplication applicationWillTerminate:],在这种情况下,我们不知道是否applicationWillEnterBackground:已被调用;

    3. 崩溃了,只能使用某种崩溃报告工具来完成。(编辑:捕捉SIGKILL是不可能的)

  • 相关阅读:
    upgrade和update的区别
    批处理文件的几种路径扩展
    CMD does not support UNC paths as current directories.的巧妙解决方案
    让批处理不回显错误信息
    python中那纠结的os.system()与空格处理
    jQuery Mobel 学习相关资料整理(一)
    c#获取某月的第一天和某月的最后一天
    Umbraco网站制作(七) 调用外部用户控件
    Umbraco网站制作(八) 实现伪静态
    Timeout 时间已到。在操作完成之前超时时间已过或服务器未响应。
  • 原文地址:https://www.cnblogs.com/itlover2013/p/14058121.html
Copyright © 2011-2022 走看看