diff --git a/demo/GYBootingProtectionDemo/ViewController.m b/demo/GYBootingProtectionDemo/ViewController.m index 387c166..54aa877 100644 --- a/demo/GYBootingProtectionDemo/ViewController.m +++ b/demo/GYBootingProtectionDemo/ViewController.m @@ -16,12 +16,13 @@ @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; - + NSLog(@"------------ Root view did load ------------"); _button = [[UIButton alloc] initWithFrame:CGRectMake(50, 50, 200, 30)]; [self.button setTitle:@"Make a crash" forState:UIControlStateNormal]; [self.button setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; [self.button addTarget:self action:@selector(pressedButton) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.button]; + // [self pressedButton]; } - (void)pressedButton { diff --git a/src/AppDelegate+GYBootingProtection.m b/src/AppDelegate+GYBootingProtection.m index 7e1c230..1aeb105 100644 --- a/src/AppDelegate+GYBootingProtection.m +++ b/src/AppDelegate+GYBootingProtection.m @@ -15,9 +15,25 @@ static NSString *const cancelButtonTitle = @"取消"; static NSString *const createCrashButtonTitle = @"制造Crash!"; static NSString *const mainStoryboardInfoKey = @"UIMainStoryboardFile"; +static const char *kOriginalControllerKey = "kOriginalControllerKey"; + +@interface AppDelegate() +@property (nonatomic, strong) UIViewController *originalRootViewController; +@end @implementation AppDelegate (GYBootingProtection) +- (UIViewController *)originalRootViewController { + return objc_getAssociatedObject(self, kOriginalControllerKey); +} + +- (void)setOriginalRootViewController:(UIViewController *)originalRootViewController { + objc_setAssociatedObject(self, + kOriginalControllerKey, + originalRootViewController, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + /* * 连续闪退检测前需要执行的逻辑,如上报统计初始化 */ @@ -35,8 +51,8 @@ - (void)onBeforeBootingProtection { }]; // 彩蛋: 弹 Tips 询问是否制造 crash - [GYBootingProtection setStartupCrashForTest:YES]; - [self showAlertForCreateCrashIfNeeded]; +// [GYBootingProtection setStartupCrashForTest:YES]; +// [self showAlertForCreateCrashIfNeeded]; } @@ -54,6 +70,7 @@ - (void)onBootingProtection { - (void)onBootingProtectionWithCompletion:(BoolCompletionBlock)completion { [self onBootingProtection]; #pragma mark TODO 如果需要异步修复,在完成后调用 completion + // 正常启动流程 if (completion) completion(); } @@ -71,7 +88,10 @@ - (BOOL)swizzled_application:(UIApplication *)application didFinishLaunchingWith /* ------- 启动连续闪退保护 ------- */ [GYBootingProtection setBoolCompletionBlock:^BOOL{ - + if (self.originalRootViewController) { + NSLog(@"-------- Orininal root controller: %@", self.originalRootViewController); + self.window.rootViewController = self.originalRootViewController; + } // 原 didFinishLaunch 正常启动流程 return [self swizzled_application:application didFinishLaunchingWithOptions:launchOptions]; }]; @@ -132,9 +152,13 @@ - (void)showAlertForCreateCrashIfNeeded { */ - (void)presentAlertViewController:(UIAlertController *)alertController { if (![self hasStoryboardInfo]) { + // 不使用 storyboard 时,真正的 rootController 会在原 didFinishLaunch 中初始化,不需要额外处理 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - self.window.rootViewController = [[UIViewController alloc] init]; + } else { + // 使用 storyboard 时,需要把 rootController 存下来,待修复完成后,重新设置 self.window.rootViewController + self.originalRootViewController = self.window.rootViewController; } + self.window.rootViewController = [[UIViewController alloc] init]; [self.window makeKeyAndVisible]; [self.window.rootViewController presentViewController:alertController animated:YES completion:nil]; }