经过替换UINavigationController的(pushViewController:animated:)方法,可以看到push一个Controller的NavigationController的所有子Controllers.
问题重现步骤是:登录完成立即startApp
原因是:startApp的控制器是在登录的UINavigationController进行push的。
解决办法:1.等登录页完全dismiss再startApp
2.使用window根视图控制器push
分析:startApp为什么使用登录的UINavigationController进行push
反编译查看伪源码,是调用的-[DFNavigationController pushViewController:animated:]这个方法
void -[DFNavigationController pushViewController:animated:](void * self, void * _cmd, void * arg2, bool arg3) {
r13 = arg3;
r12 = self;
r14 = [arg2 retain];
if ([APCheckUtils checkOperationInMainThread:@"pushViewController" object:r14] != 0x0) {
if (r14 != 0x0) {
rbx = [[r12 viewControllers] retain];
rax = [rbx containsObject:r14];
var_-56 = r12;
[rbx release];
rbx = var_-56;
if (rax != 0x0) {
_APLogToFile(@"APMobileRuntime", 0x4e20, @"Pushing the same vc %@", r14);
}
else {
[rbx setPushingVC:r14];
CACurrentMediaTime();
[r14 setPushTs:r14];
[r14 setIsAlipayExiting:0x0];
rdx = [DTViewController class];
if ([r14 isKindOfClass:rdx] != 0x0) {
r12 = [[rbx interactivePopGestureRecognizer] retain];
rdx = 0x0;
[r12 setEnabled:rdx];
[r12 release];
}
var_-44 = r13;
rbx = [[rbx viewControllers] retain];
r15 = [[rbx lastObject] retain];
[rbx release];
if ((r15 != 0x0) && ([r15 respondsToSelector:@selector(beforePushViewController)] != 0x0)) {
[r15 performSelector:@selector(beforePushViewController) withObject:0x0];
}
var_-72 = r15;
r15 = @selector(microApplication);
rbx = [_objc_msgSend(r14, r15) retain];
[rbx release];
if (rbx == 0x0) {
r13 = [[DFMicroApplication currentApplication] retain];
[r14 setMicroApplication:r13];
rbx = [[r13 viewControllers] retain];
[rbx addObject:r14];
r15 = @selector(microApplication);
[rbx release];
[r13 release];
}
rbx = [_objc_msgSend(r14, r15) retain];
r12 = @selector(viewControllers);
r13 = [[rbx viewControllers] retain];
rax = [r13 count];
var_-64 = rbx;
if (rax != 0x0) {
rbx = [_objc_msgSend(rbx, r12) retain];
r12 = [rbx indexOfObject:r14];
[rbx release];
[r13 release];
COND = r12 != 0x0;
r15 = var_-44;
r12 = var_-56;
if (!COND) {
rdx = [UITabBarController class];
if ([r14 isKindOfClass:rdx] != 0x0) {
r15 = [[r14 viewControllers] retain];
r13 = [[r15 firstObject] retain];
[r15 release];
if (r13 != 0x0) {
[r13 setIsAppFirstVC:0x1];
}
[r13 release];
r15 = var_-44;
}
else {
[r14 setIsAppFirstVC:0x1];
}
}
}
else {
[r13 release];
r15 = var_-44;
r12 = var_-56;
}
if ([r12 checkPresentingForViewController:r12] != 0x0) {
rbx = [[r12 presentedViewController] retain];
r15 = [[r12 presentedNavigationController:rbx] retain];
[rbx release];
[r15 pushViewController:r14 animated:var_-44 & 0xff];
rbx = [[r15 viewControllers] retain];
_APLogToFile(@"APMobileRuntime", 0x4e20, @"Push VC into presentedViewController %@", rbx);
[rbx release];
[r15 release];
}
else {
[r12 setIsPopOperation:0x0];
var_-88 = r12;
*(&var_-88 + 0x8) = _OBJC_CLASS_$_DFNavigationController;
[[&var_-88 super] pushViewController:r14 animated:r15 & 0xff];
_APLogToFile(@"APMobileRuntime", 0x4e20, @"Push VC %@", r14);
}
[var_-64 release];
[var_-72 release];
}
}
else {
_APLogToFile(@"APMobileRuntime", 0x4e20, @"Pushing the same vc %@", r14);
}
}
[r14 release];
return;
}
我们看push的代码
明显的:检查有presentedViewController就用presentedNavigationController跳转。
而且还写了日志
/**
* 内部使用,业务不要用。
*/
void APLogToFile(NSString *tag, int level, NSString *format, ...) NS_FORMAT_FUNCTION(3,4);
function _APLogToFile {
r31 = r31 - 0x110;
*(r31 + 0xb0) = r28;
*(0xc0 + r31) = r27;
*(r31 + 0xc0) = r26;
*(0xd0 + r31) = r25;
*(r31 + 0xd0) = r24;
*(0xe0 + r31) = r23;
*(r31 + 0xe0) = r22;
*(0xf0 + r31) = r21;
*(r31 + 0xf0) = r20;
*(0x100 + r31) = r19;
*(r31 + 0x100) = r29;
*(0x110 + r31) = r30;
r29 = r31 + 0x100;
r26 = r1;
*(r29 + 0xffffffffffffffa8) = *___stack_chk_guard;
r28 = [r0 retain];
r20 = [[r2 retain] retain];
if (*(int32_t *)0x102dbe5b4 == -0x1) goto loc_100e04adc;
loc_100e04a1c:
if (r20 == 0x0) goto loc_100e04bb4;
loc_100e04a20:
*r31 = [r20 class];
r0 = [NSString stringWithFormat:@"%@", r3];
r29 = r29;
r0 = [r0 retain];
[r0 hasSuffix:@"ConstantString"];
[r0 release];
[r20 release];
if (r26 < zero_extend_64(0x4e20)) goto loc_100e051a8;
loc_100e04a98:
if (!CPU_FLAGS & E) {
*(r31 + 0x68) = r29 + 0x10;
r0 = [NSString alloc];
r3 = *(r31 + 0x68);
r25 = [r0 initWithFormat:r20 arguments:r3];
}
else {
r24 = [NSString alloc];
*r31 = [r20 class];
*(r31 + 0x10) = r20;
r25 = [r24 initWithFormat:@"LOG ERROR:Forbid using non-constant format string, for potential crash!-%@-%@", r3, stack[2048]];
}
*(int128_t *)(r29 + 0xffffffffffffff98) = q0;
*(int128_t *)(r29 + 0xffffffffffffff88) = q0;
[NSString alloc];
gettimeofday(r31 + 0x78, zero_extend_64(0x0));
time(r31 + 0x70);
r0 = localtime(r31 + 0x70);
r8 = sign_extend_64(*(int32_t *)(r31 + 0x80));
r9 = zero_extend_64(0x4dd3);
asm { movk w9, #0x1062, lsl #16 };
r8 = (r9 * r8 * r9 >> 0x3f) + (r9 * r8 * r9 >> 0x20) / 0x40;
asm { sxtw x8, w8 };
*(r0 + 0x28) = r8;
r10 = *(0x20 + r0) + 0x76c;
r9 = *(r0 + 0x10) + 0x1;
*(r31 + 0x28) = *r0;
*(0x38 + r31) = r8;
*(r31 + 0x18) = *(r0 + 0x8);
*(0x28 + r31) = *(r0 + 0x10);
*(r31 + 0x8) = r9;
*(0x18 + r31) = *(0x18 + r0);
*r31 = r10;
__sprintf_chk(r29 - 0x78, zero_extend_64(0x0), 0x20, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d.%.3ld");
r24 = [[NSThread currentThread] retain];
*0x102dbe5a8 = *0x102dbe5a8 + 0x1;
*(r31 + 0x18) = r28;
*(0x28 + r31) = r25;
*(r31 + 0x8) = r24;
*(0x18 + r31) = *0x102dbe5a8;
*r31 = r29 - 0x78;
r2 = @"%s [%p] %lld: %@ %@";
r27 = objc_msgSend(r23, r22);
[r24 release];
r0 = [APLogMgr sharedInstance];
r29 = r29;
r0 = [r0 retain];
r24 = [r0 logPrintEnable];
[r0 release];
if (r24 != 0x0) {
*r31 = r28;
*(r31 + 0x10) = r25;
NSLog(@"[MPDebugLog] %@ : %@", r1, r2);
}
r21 = *(int32_t *)0x102dbe5b0;
*(r31 + 0x58) = r27;
*(0x68 + r31) = r28;
if (r21 == -0x1) {
*(r31 + 0x48) = r20;
r20 = r26;
r0 = [APLogMgr sharedInstance];
r0 = [r0 retain];
r26 = r0;
r0 = [r0 delegate];
r29 = r29;
r0 = [r0 retain];
r28 = [r0 respondsToSelector:@selector(isCloseLogEncrypt)];
[r0 release];
[r26 release];
if (r28 != 0x0) {
r0 = [APLogMgr sharedInstance];
r0 = [r0 retain];
r26 = r0;
r0 = [r0 delegate];
r29 = r29;
r0 = [r0 retain];
*(int32_t *)0x102dbe5b0 = [r0 isCloseLogEncrypt];
[r0 release];
[r26 release];
}
r21 = *(int32_t *)0x102dbe5b0;
r27 = *(r31 + 0x58);
r28 = *(0x68 + r31);
r26 = r20;
r20 = *(r31 + 0x48);
}
r24 = [[r27 stringByAppendingString:@"\\r\\n"] retain];
[r25 release];
r0 = [APFileLog sharedInstance];
r29 = r29;
r22 = [r0 retain];
*(int32_t *)(r31 + 0x54) = r26;
if (r21 == 0x1) {
[r22 writeFileLog:r24];
[r22 release];
r0 = [APLogMgr sharedInstance];
r0 = [r0 retain];
r26 = r0;
r0 = [r0 delegate];
r29 = r29;
r0 = [r0 retain];
r21 = [r0 respondsToSelector:@selector(logWithoutEncrypt:)];
[r0 release];
[r26 release];
if (r21 != 0x0) {
r0 = [APLogMgr sharedInstance];
r0 = [r0 retain];
r0 = [r0 delegate];
r29 = r29;
r0 = [r0 retain];
[r0 logWithoutEncrypt:r24];
[r26 release];
[r21 release];
}
*(r31 + 0x48) = [*(r31 + 0x60) retain];
r22 = [r24 retain];
r0 = [APLogMgr sharedInstance];
r0 = [r0 retain];
r21 = r0;
r0 = [r0 delegate];
r29 = r29;
r0 = [r0 retain];
r28 = [r0 respondsToSelector:@selector(logExtra:level:logString:), r3, stack[2048]];
[r0 release];
[r21 release];
if (r28 != 0x0) {
r0 = [APLogMgr sharedInstance];
r0 = [r0 retain];
r0 = [r0 delegate];
r29 = r29;
r0 = [r0 retain];
r3 = *(int32_t *)(r31 + 0x54);
[r0 logExtra:*(r31 + 0x48) level:r3 logString:stack[2048]];
[r21 release];
[r19 release];
}
r0 = r22;
}
else {
r3 = r26;
[r22 writeAesFileLog:r24 level:r3];
[r22 release];
*(r31 + 0x48) = [r28 retain];
r28 = [r24 retain];
r0 = [APLogMgr sharedInstance];
r0 = [r0 retain];
r19 = r0;
r0 = [r0 delegate];
r29 = r29;
r0 = [r0 retain];
r27 = [r0 respondsToSelector:@selector(logExtra:level:logString:), r3, stack[2048]];
[r0 release];
[r19 release];
if (r27 != 0x0) {
r0 = [APLogMgr sharedInstance];
r0 = [r0 retain];
r0 = [r0 delegate];
r29 = r29;
r0 = [r0 retain];
r3 = *(int32_t *)(r31 + 0x54);
[r0 logExtra:*(r31 + 0x48) level:r3 logString:stack[2048]];
[r21 release];
[r19 release];
}
r0 = r28;
}
[r0 release];
[*(r31 + 0x48) release];
r0 = [APLogMgr sharedInstance];
r0 = [r0 retain];
r19 = r0;
r0 = [r0 listenerDelegate];
r29 = r29;
r22 = [r0 retain];
[r19 release];
r0 = [r22 respondsToSelector:@selector(logExtra:level:logString:), r3, stack[2048]];
r19 = *(r31 + 0x58);
r28 = *(0x68 + r31);
if (r0 != 0x0) {
[r22 logExtra:r28 level:*(int32_t *)(r31 + 0x54) logString:stack[2048]];
}
[r22 release];
[r19 release];
r0 = r24;
goto loc_100e051a4;
loc_100e051a4:
[r0 release];
goto loc_100e051a8;
loc_100e051a8:
[r20 release];
r0 = [r28 release];
if (*___stack_chk_guard != *(r29 + 0xffffffffffffffa8)) {
r0 = __stack_chk_fail();
}
return r0;
loc_100e04bb4:
r0 = r20;
goto loc_100e051a4;
loc_100e04adc:
r21 = r20;
r20 = r26;
r0 = [APLogMgr sharedInstance];
r0 = [r0 retain];
r25 = r0;
r0 = [r0 delegate];
r29 = r29;
r0 = [r0 retain];
r27 = [r0 respondsToSelector:@selector(isLogFormatAssertCheck)];
[r0 release];
[r25 release];
if (r27 != 0x0) {
r0 = [APLogMgr sharedInstance];
r0 = [r0 retain];
r22 = r0;
r0 = [r0 delegate];
r29 = r29;
r0 = [r0 retain];
*(int32_t *)0x102dbe5b4 = [r0 isLogFormatAssertCheck];
[r0 release];
[r22 release];
}
else {
*(int32_t *)0x102dbe5b4 = 0x0;
}
r26 = r20;
r20 = r21;
if (r20 != 0x0) goto loc_100e04a20;
}
没看到把日志写哪了