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

来源:互联网 发布:sql server怎么下载 编辑:程序博客网 时间:2024/06/06 11:48

问题描述:当用户更新应用程序后,直接点击 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:方法在使窗口在屏幕上可见之前完成。
建议以后把显示主窗口的代码放到这个方法里。

原创粉丝点击