iOS -从 AppStore 打开应用程序奔溃

问题描述:当用户更新应用程序后,直接点击 AppStore 上的“打开”按钮发生奔溃。
解决过程:

1.首先以为是使用 Userdefault 存储版本号出错了。后来经过测试,Userdefault 如果存了一个空值,是不会在 plist 文件里新增一个键值对的,也不会报错。但是给字典存一个 nil,肯定会奔溃的。
2.后来又怀疑切换根视图控制器出了问题。当我设置根视图控制器为引导页视图控制器时,不会发生错误。也就是说从引导页视图控制器切换为 tabbar 视图控制器没有问题,多虑了。
3.因为是从AppStore 打开就会闪退,于是怀疑跟第三方应用打开app 有关。于是新建一个项目,专门负责打开 app。发现错误再现!
4.在应用程序加载时我做了什么?经过缜密的思考发现了这么一段代码

if (launchOptions) {


            XYMessageVC *vc = [[XYMessageVC alloc] init];
            vc.title = @"系统通知";
            XYTabBarController *tabbar = (XYTabBarController *)self.window.rootViewController;

            UINavigationController *nav = tabbar.selectedViewController;
            [nav pushViewController:vc animated:YES];

    }

就是上面这段代码,疏忽了对 app 打开方式的具体判断。这个代码块本来是想处理点击远程推送消息进入 app 的,但是没有具体到各种情况。第一次下载 app,包括更新 app 后启动,是没有XYTabBarController的,所以会奔溃了。
将代码改为

if (launchOptions) {
        if(launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {

            XYMessageVC *vc = [[XYMessageVC alloc] init];
            vc.title = @"系统通知";
            XYTabBarController *tabbar = (XYTabBarController *)self.window.rootViewController;

            UINavigationController *nav = tabbar.selectedViewController;
            [nav pushViewController:vc animated:YES];
        }
    }

这样就安全了。因为是接手别人的项目,所以项目中的具体逻辑需要自己慢慢判断。

知识总结:
1.判断启动途径

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
    // Override point for customization after application launch.  


    //用户自己点击启动  
    if(!launchOptions)  
    {  
        NSLog(@"用户点击app启动");  
    }  
    else  
    {  
        NSURL *url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];  
        //app 通过urlscheme启动  
        if (url) {  
            NSLog(@"app 通过urlscheme启动 url = %@",url);  
        }  
        UILocalNotification *localNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];  
        //通过本地通知启动  
        if(localNotification)  
        {  
            NSLog(@"app 通过本地通知启动 localNotification = %@",localNotification);  
        }  
        NSDictionary *remoteCotificationDic = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];  
        //远程通知启动  
        if(remoteCotificationDic)  
        {  
            NSLog(@"app 通过远程推送通知启动 remoteCotificationDic = %@",remoteCotificationDic);  
        }  

    }  
    return YES;  
}  

2.应用A 打开应用 B :

1.在应用B 中添加 URLScheme,可以随意命名,假如命名为 appB(也就是给 B 起个名字,别人一叫他就答应).
2.在 A 的 info.plist 文件中加入白名单,LSApplicationQueriesSchemes, 内容为数组。把 appB 加入。
3.在应用 A 中执行代码
NSURL *url = [NSURL URLWithString:@"appB://"];
    // 如果已经安装了这个应用,就跳转
    if ([[UIApplication sharedApplication] canOpenURL:url]) {
        [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
    }

3.翻阅官方文档后,方法
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions NS_AVAILABLE_IOS(6_0);
有这么一段描述
If your app relies on the state restoration machinery to restore its view controllers, always show your app’s window from this method. Do not show the window in your app’s application:didFinishLaunchingWithOptions: method. Calling the window’s makeKeyAndVisible method does not make the window visible right away anyway. UIKit waits until your app’s application:didFinishLaunchingWithOptions: method finishes before making the window visible on the screen.
大概意思:如果您的应用程序依赖于状态恢复机制来恢复其视图控制器,请始终使用此方法显示应用程序的窗口。不要在方法application:didFinishLaunchingWithOptions:method显示窗口。调用窗口的makeKeyAndVisible方法不会使窗口立即显示。 UIKit等待您的应用程序的应用程序:didFinishLaunchingWithOptions:方法在使窗口在屏幕上可见之前完成。
建议以后把显示主窗口的代码放到这个方法里。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lucy-JY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值