第一个页面:H5-1
第二个页面:H5-2
第三个页面:原生-1
H5-1 -> H5-2 -> 原生-1
当 原生-1 返回到 H5-2 再返回到 H5-1时 数据丢失
思路:
1.hopper一下JsApiHandler4PopWindow源代码发现kNBSessionPopData 这个就是携带的返回数据
void -[JsApiHandler4PopWindow handler:context:callback:](void * self, void * _cmd, void * arg2, void * arg3, void * arg4) {
stack[2048] = arg4;
r31 = r31 - 0x170;
*(r31 + 0x110) = r28;
*(0x120 + r31) = r27;
*(r31 + 0x120) = r26;
*(0x130 + r31) = r25;
*(r31 + 0x130) = r24;
*(0x140 + r31) = r23;
*(r31 + 0x140) = r22;
*(0x150 + r31) = r21;
*(r31 + 0x150) = r20;
*(0x160 + r31) = r19;
*(r31 + 0x160) = r29;
*(0x170 + r31) = r30;
r29 = r31 + 0x160;
*(r29 + 0xffffffffffffffa0) = *___stack_chk_guard;
r27 = [arg2 retain];
r28 = [arg3 retain];
*(r31 + 0x70) = self;
*(0x80 + r31) = _OBJC_CLASS_$_JsApiHandler4PopWindow;
[[r31 + 0x70 super] handler:r27 context:r28 callback:stack[2048]];
if ([r27 isKindOfClass:[NSDictionary class]] != 0x0) {
r0 = [r27 objectForKeyedSubscript:@"data"];
r29 = r29;
r0 = [r0 retain];
[r0 release];
if (r0 != 0x0) {
r21 = [[r28 currentSession] retain];
r0 = [r27 objectForKeyedSubscript:@"data"];
r29 = r29;
r19 = [r0 retain];
[r21 setExpando:@"kNBSessionPopData" withValue:r19];
[r19 release];
[r21 release];
}
}
r25 = @selector(currentViewController);
r0 = objc_msgSend(r28, r25);
r0 = [r0 retain];
r19 = r0;
r0 = [r0 session];
r0 = [r0 retain];
r21 = r0;
*r31 = @selector(subObjects);
r0 = [r0 subObjects];
r0 = [r0 retain];
r23 = [r0 mutableCopy];
[r0 release];
[r21 release];
[r19 release];
r0 = [NSMutableArray array];
r29 = r29;
*(r31 + 0x28) = [r0 retain];
*(r31 + 0x50) = q0;
*(0x60 + r31) = q0;
*(r31 + 0x30) = q0;
*(0x40 + r31) = q0;
r0 = [r23 retain];
r23 = r0;
*(r31 + 0x20) = @selector(countByEnumeratingWithState:objects:count:);
r0 = [r0 countByEnumeratingWithState:r31 + 0x30 objects:r31 + 0x80 count:stack[2048]];
if (r0 != 0x0) {
r26 = r0;
*(r31 + 0x8) = @selector(currentViewController);
*(0x18 + r31) = r28;
*(r31 + 0x18) = r27;
r19 = zero_extend_64(0x0);
r25 = **(r31 + 0x40);
do {
r22 = zero_extend_64(0x0);
do {
if (**(r31 + 0x40) != r25) {
objc_enumerationMutation(r23);
}
r21 = [*(*(r31 + 0x38) + r22 * 0x8) retain];
[r19 release];
r0 = [r21 viewController];
r29 = r29;
r0 = [r0 retain];
r20 = [r0 isTagEvicted];
[r0 release];
if (r20 != 0x0) {
[*(r31 + 0x28) addObject:r21];
}
r22 = r22 + 0x1;
r19 = r21;
} while (r22 < r26);
r0 = objc_msgSend(r23, *(r31 + 0x20));
r26 = r0;
r19 = r21;
} while (r0 != 0x0);
[r21 release];
r28 = *(r31 + 0x10);
r27 = *(0x20 + r31);
r25 = *(r31 + 0x8);
}
[r23 release];
[r23 removeObjectsInArray:*(r31 + 0x28)];
if ([r23 count] < 0x2) goto loc_101acd4a4;
loc_101acd434:
r0 = objc_msgSend(r28, r25);
r29 = r29;
r0 = [r0 retain];
r19 = r0;
if ([r0 isChildTab] == 0x0) goto loc_101acd468;
loc_101acd45c:
[r19 release];
goto loc_101acd4a4;
loc_101acd4a4:
r0 = objc_msgSend(r28, r25);
r29 = r29;
r0 = [r0 retain];
[r0 clearAndBack];
r0 = r0;
goto loc_101acd4cc;
loc_101acd4cc:
[r0 release];
[*(r31 + 0x28) release];
[r23 release];
[r28 release];
[r27 release];
if (*___stack_chk_guard != *(r29 + 0xffffffffffffffa0)) {
__stack_chk_fail();
}
return;
loc_101acd468:
r0 = objc_msgSend(r28, r25);
r29 = r29;
r0 = [r0 retain];
r21 = [r0 hasChildTab];
[r0 release];
[r19 release];
if (r21 != 0x0) {
r0 = objc_msgSend(r28, r25);
r29 = r29;
r0 = [r0 retain];
[r0 clearAndBack];
r0 = r0;
}
else {
r0 = [r23 count];
r22 = r25;
r25 = r0;
r0 = [r28 currentSession];
r0 = [r0 retain];
r19 = r0;
r0 = objc_msgSend(r0, *r31);
r0 = [r0 retain];
r21 = [[r0 firstObject] retain];
[r0 release];
[r19 release];
r0 = [r21 viewController];
r29 = r29;
r0 = [r0 retain];
r19 = r0;
r20 = [r0 childTabCount];
[r19 release];
if (r25 - 0x2 < r20) {
asm { ccmp x20, #0x0, #0x4 };
}
if (CPU_FLAGS & E) {
asm { csel x19, x8, xzr, eq };
}
r0 = objc_msgSend(r28, r22);
r29 = r29;
r0 = [r0 retain];
[r0 popToWindowOfIndex:r19];
[r0 release];
r0 = r21;
}
goto loc_101acd4cc;
}
2.全局搜索kNBSessionPopData
0000000102b199c0 dq ___CFConstantStringClassReference, 0x7c8, _amf_base64EncodedStringWithWrapWidth:.lookup+141700, 0x11 ; "kNBSessionPopData", DATA XREF=-[NBViewControllerProxy lifecycle_viewDidAppear:]+92, -[JsApiHandler4PopTo handler:context:callback:]+2476, -[JsApiHandler4PopTo handler:context:callback:]+2520, -[JsApiHandler4PopWindow handler:context:callback:]+288
3.可以看到这个就是取值的方法-[NBViewControllerProxy lifecycle_viewDidAppear:]
4.查看其代码主动调用的[r19 callHandler:@"resume" data:r22 responseCallback:stack[2048]];把数据传给了H5
void -[NBViewControllerProxy lifecycle_viewDidAppear:](void * self, void * _cmd, bool arg2) {
*(r31 + 0xffffffffffffffb0) = r26;
*(0xffffffffffffffc0 + r31) = r25;
r31 = r31 + 0xffffffffffffffb0;
*(r31 + 0x10) = r24;
*(0x20 + r31) = r23;
*(r31 + 0x20) = r22;
*(0x30 + r31) = r21;
*(r31 + 0x30) = r20;
*(0x40 + r31) = r19;
*(r31 + 0x40) = r29;
*(0x50 + r31) = r30;
r29 = r31 + 0x40;
r19 = self;
if ([*(self + 0x58) isViewReady] != 0x0) {
r0 = [r19 psdSession];
r0 = [r0 retain];
r20 = [objc_msgSend(r0, @selector(getExpando:)) retain];
[r0 release];
r0 = [r19 psdSession];
r0 = [r0 retain];
[r0 deleteExpando:@"kNBSessionPopData"];
[r21 release];
r0 = [r19 psdSession];
r0 = [r0 retain];
r21 = [objc_msgSend(r0, @selector(getExpando:)) retain];
[r0 release];
r0 = [r19 psdSession];
r29 = r29;
r0 = [r0 retain];
[r0 deleteExpando:@"kNBSessionResumeParams"];
[r22 release];
if (r21 != 0x0) {
r22 = [[NSMutableDictionary dictionary] retain];
[r22 setObject:[@(0x1) retain] forKeyedSubscript:@"__pull__"];
[r24 release];
[r22 setObject:r21 forKeyedSubscript:@"resumeParams"];
if (r20 != 0x0) {
[r22 setObject:r20 forKeyedSubscript:@"data"];
}
r22 = [r22 retain];
[r20 release];
[r19 callHandler:@"resume" data:r22 responseCallback:stack[2048]];
[r19 callHandler:@"pageResume" data:r22 responseCallback:stack[2048]];
[r22 release];
r20 = r22;
}
else {
[r19 callHandler:@"resume" data:r20 responseCallback:stack[2048]];
[r19 callHandler:@"pageResume" data:r20 responseCallback:stack[2048]];
}
[r21 release];
[r20 release];
}
else {
[*(r19 + 0x58) setIsViewReady:0x1];
}
[r19 performSelector:@selector(executeDelayTasks) withObject:zero_extend_64(0x0) afterDelay:stack[2048]];
return;
}
5.对-[PSDJsBridge callHandler:data:responseCallback:]方法进行hook打印
发现 原生-1 返回到 H5-2的 时候返回数据是有的 , H5-2 再返回到 H5-1时数据丢失。
6.但是 原生-1 返回到 H5-2 使用的是 [temVC.navigationController popViewControllerAnimated:YES]
为什么这页 返回到 H5-2 打印了数据呢?
因为popViewControllerAnimated:YES 需要时间。
因为由代码可以看出只要页面出现viewDidAppear 就会调用callHandler:data:responseCallback。
原生-1 返回到 H5-2 全部代码是下面这两行。
[tempVC.navigationController popViewControllerAnimated:YES];
callback(dic);
页面没有完全返回到上一页就调用了callback。callback又调用了popwindow。所以返回数据作用到了H5-2页面。
7.这样的问题在蚂蚁mPaas框架了已经不是第1,2次遇到了.......
都是由于这0.25秒的动画导致的。
解决办法:
1.原生返回去掉动画
2.h5延迟调用