Last active
September 16, 2020 06:26
-
-
Save madordie/dbeac4f6eee4d9659f547594f0f75160 to your computer and use it in GitHub Desktop.
探究UIScrollView的嵌套时手势作用在谁身上的问题
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
char __cdecl -[UIScrollViewPanGestureRecognizer _canTransferTrackingFromParentPagingScrollView](UIScrollViewPanGestureRecognizer *self, SEL a2) | |
{ | |
double v2; // xmm0_8 | |
double v3; // xmm1_8 | |
UIScrollView *v4; // rax | |
void *v5; // rax | |
void *v6; // r13 | |
void *v7; // rax | |
void *v8; // r14 | |
UIView *v9; // rax | |
__int64 v10; // rbx | |
bool v11; // r15 | |
char v12; // r12 | |
char v14; // al | |
_BOOL8 v15; // rcx | |
_BOOL8 v16; // rdx | |
double v17; // xmm0_8 | |
double v18; // xmm0_8 | |
__int128 v19; // [rsp+0h] [rbp-90h] | |
__int128 v20; // [rsp+10h] [rbp-80h] | |
__int128 v21; // [rsp+20h] [rbp-70h] | |
__int128 v22; // [rsp+30h] [rbp-60h] | |
double v23; // [rsp+40h] [rbp-50h] | |
double v24; // [rsp+48h] [rbp-48h] | |
double v25; // [rsp+50h] [rbp-40h] | |
double v26; // [rsp+58h] [rbp-38h] | |
BOOL v27; // [rsp+60h] [rbp-30h] | |
char v28; // [rsp+66h] [rbp-2Ah] | |
char v29; // [rsp+67h] [rbp-29h] | |
v4 = -[UIScrollViewPanGestureRecognizer scrollView](self, "scrollView"); | |
v5 = (void *)objc_retainAutoreleasedReturnValue(v4); | |
v6 = v5; | |
v7 = objc_msgSend(v5, "_parentScrollView"); | |
v8 = (void *)objc_retainAutoreleasedReturnValue(v7); | |
if ( (unsigned __int8)objc_msgSend(v8, "isPagingEnabled") | |
&& (unsigned __int8)objc_msgSend(v6, "_transfersScrollToContainer") ) | |
{ | |
v27 = 0; | |
v9 = -[UIGestureRecognizer view](self, "view"); | |
v10 = objc_retainAutoreleasedReturnValue(v9); | |
-[UIScrollViewPanGestureRecognizer translationInView:](self, "translationInView:", v10); | |
v25 = v2; | |
v26 = v3; | |
objc_release(v10); | |
v29 = (unsigned __int64)objc_msgSend(v6, "_canScrollX"); | |
v28 = (unsigned __int64)objc_msgSend(v6, "_canScrollY"); | |
if ( (unsigned __int8)objc_msgSend(v8, "_canScrollX") ) | |
v27 = (unsigned __int8)objc_msgSend(v8, "isScrollEnabled") != 0; | |
if ( (unsigned __int8)objc_msgSend(v8, "_canScrollY") ) | |
v11 = (unsigned __int8)objc_msgSend(v8, "isScrollEnabled") != 0; | |
else | |
v11 = 0; | |
if ( v6 ) | |
{ | |
objc_msgSend_stret(&v21, (const char *)v6, "contentInset"); | |
objc_msgSend_stret(&v19, (const char *)v6, "bounds"); | |
} | |
else | |
{ | |
v2 = 0.0; | |
v22 = 0LL; | |
v21 = 0LL; | |
v20 = 0LL; | |
v19 = 0LL; | |
} | |
objc_msgSend(v6, "contentSize", v19); | |
v24 = v2; | |
v23 = v3; | |
v14 = (unsigned __int64)objc_msgSend(v6, "_currentlyAbuttedContentEdges", v19); | |
LODWORD(v15) = 0; | |
LODWORD(v16) = 0; | |
if ( v29 ) | |
{ | |
v17 = v24 + *((double *)&v21 + 1) + *((double *)&v22 + 1); | |
v16 = v17 <= *(double *)&v20; | |
LOBYTE(v16) = v17 > *(double *)&v20; | |
} | |
if ( v28 ) | |
{ | |
v18 = v23 + *(double *)&v21 + *(double *)&v22; | |
v15 = v18 <= *((double *)&v20 + 1); | |
LOBYTE(v15) = v18 > *((double *)&v20 + 1); | |
} | |
if ( v14 & 0xA && v27 && (_DWORD)v16 || (v12 = 0, v14 & 5) && (_DWORD)v15 && v11 == 1 ) | |
{ | |
v12 = 1; | |
if ( (!v27 || v25 <= 0.0 || !(v14 & 2)) | |
&& (!v27 || v25 >= 0.0 || !(v14 & 8)) | |
&& (v26 <= 0.0 || !(v14 & 1) || v11 != 1) ) | |
{ | |
v12 = 0; | |
} | |
} | |
} | |
else | |
{ | |
v12 = 0; | |
} | |
objc_release(v8); | |
objc_release(v6); | |
return v12; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
char __cdecl -[UIScrollViewPanGestureRecognizer _shouldTryToBeginWithEvent:](UIScrollViewPanGestureRecognizer *self, SEL a2, id a3) | |
{ | |
double v3; // xmm0_8 | |
double v4; // xmm1_8 | |
__int64 event; // rbx | |
UIScrollView *v6; // rax | |
void *scrollView; // rbx | |
bool canScrollX; // r14 | |
bool v9; // r14 | |
bool canScrollY; // r15 | |
UIView *v11; // rax | |
__int64 v12; // rbx | |
void *v13; // r15 | |
void *v15; // rax | |
__int64 v16; // rax | |
__int64 v17; // r14 | |
__int64 v18; // rax | |
void *v19; // rax | |
void *v20; // rbx | |
__int64 v21; // r14 | |
void *v22; // r15 | |
void *v23; // rax | |
void *v24; // rbx | |
void *v25; // rax | |
void *v26; // rbx | |
double v27; // xmm1_8 | |
void *v28; // rdx | |
void *v29; // rbx | |
void *v30; // r14 | |
bool v31; // bl | |
__int64 v32; // rdx | |
__int64 v33; // rcx | |
_BOOL8 v34; // r15 | |
char v35; // r14 | |
bool v36; // zf | |
char v37; // bl | |
UIScrollViewPanGestureRecognizer *v38; // [rsp+0h] [rbp-90h] | |
__objc2_class *v39; // [rsp+8h] [rbp-88h] | |
UIScrollViewPanGestureRecognizer *v40; // [rsp+10h] [rbp-80h] | |
NSObject v41; // [rsp+18h] [rbp-78h] | |
double v42; // [rsp+20h] [rbp-70h] | |
double v43; // [rsp+28h] [rbp-68h] | |
double v44; // [rsp+30h] [rbp-60h] | |
void *v45; // [rsp+38h] [rbp-58h] | |
__int64 v46; // [rsp+40h] [rbp-50h] | |
double v47; // [rsp+48h] [rbp-48h] | |
__int64 v48; // [rsp+50h] [rbp-40h] | |
void *v49; // [rsp+58h] [rbp-38h] | |
char v50; // [rsp+66h] [rbp-2Ah] | |
char v51; // [rsp+67h] [rbp-29h] | |
event = objc_retain(a3); | |
v38 = self; | |
v39 = &OBJC_CLASS___UIScrollViewPanGestureRecognizer; | |
if ( (unsigned __int8)objc_msgSendSuper2( | |
&v38, | |
"_shouldTryToBeginWithEvent:", | |
event, | |
self, | |
&OBJC_CLASS___UIScrollViewPanGestureRecognizer) ) | |
{ | |
v48 = event; | |
v6 = -[UIScrollViewPanGestureRecognizer scrollView](self, "scrollView"); | |
scrollView = (void *)objc_retainAutoreleasedReturnValue(v6); | |
if ( (unsigned __int8)objc_msgSend(scrollView, "_canScrollX") ) | |
canScrollX = (unsigned __int8)-[UIPanGestureRecognizer _canPanHorizontally](self, "_canPanHorizontally") != 0; | |
else | |
canScrollX = 0; | |
v49 = scrollView; | |
if ( (unsigned __int8)objc_msgSend(scrollView, "_canScrollY") ) | |
canScrollY = (unsigned __int8)-[UIPanGestureRecognizer _canPanVertically](self, "_canPanVertically") != 0; | |
else | |
canScrollY = 0; | |
v51 = (unsigned __int64)-[UIPanGestureRecognizer _willScrollX](self, "_willScrollX"); | |
v50 = (unsigned __int64)-[UIPanGestureRecognizer _willScrollY](self, "_willScrollY"); | |
v11 = -[UIGestureRecognizer view](self, "view"); | |
v12 = objc_retainAutoreleasedReturnValue(v11); | |
-[UIScrollViewPanGestureRecognizer translationInView:](self, "translationInView:", v12); | |
v42 = v3; | |
v43 = v4; | |
objc_release(v12); | |
if ( (canScrollY || canScrollX) != 1 || !canScrollX && canScrollY && !v50 || !canScrollY && !v51 && canScrollX ) | |
goto LABEL_12; | |
v13 = v49; | |
if ( !(*((_BYTE *)self + 432) & 0x10) ) | |
{ | |
LABEL_51: | |
v9 = (unsigned __int8)objc_msgSend(v13, "_delegateShouldPanGestureTryToBegin") != 0; | |
event = v48; | |
goto LABEL_13; | |
} | |
v15 = objc_msgSend(v49, "_actingParentScrollView"); | |
v16 = objc_retainAutoreleasedReturnValue(v15); | |
v17 = v16; | |
if ( v16 ) | |
{ | |
v18 = objc_retain(v16); | |
} | |
else | |
{ | |
v19 = objc_msgSend(v13, "_parentScrollView"); | |
v18 = objc_retainAutoreleasedReturnValue(v19); | |
} | |
v20 = (void *)v18; | |
objc_release(v17); | |
v45 = v20; | |
if ( !(unsigned __int8)-[UIScrollViewPanGestureRecognizer _isParentScrollView:consideringEvent:]( | |
self, | |
"_isParentScrollView:consideringEvent:", | |
v20, | |
v48) ) | |
{ | |
LABEL_50: | |
objc_release(v45); | |
v13 = v49; | |
goto LABEL_51; | |
} | |
v21 = (__int64)objc_msgSend(v49, "_currentlyAbuttedContentEdges"); | |
if ( *((_BYTE *)self + 432) < 0 ) | |
{ | |
if ( (unsigned __int8)-[UIScrollViewPanGestureRecognizer _shouldTransferTrackingFromParentScrollViewForCurrentOffset]( | |
self, | |
"_shouldTransferTrackingFromParentScrollViewForCurrentOffset") ) | |
{ | |
v22 = v45; | |
objc_msgSend(v45, "contentOffset"); | |
v47 = v3; | |
v44 = v4; | |
objc_msgSend(v22, "_pinContentOffsetToClosestPageBoundary"); | |
v23 = objc_msgSend(v22, "panGestureRecognizer"); | |
v24 = (void *)objc_retainAutoreleasedReturnValue(v23); | |
objc_msgSend(v24, "_cancelRecognition"); | |
v46 = v21; | |
objc_release(v24); | |
v25 = objc_msgSend(v22, "pinchGestureRecognizer"); | |
v26 = (void *)objc_retainAutoreleasedReturnValue(v25); | |
objc_msgSend(v26, "_cancelRecognition"); | |
objc_release(v26); | |
v21 = v46; | |
objc_msgSend(v22, "contentOffset"); | |
if ( v21 & 0xA ) | |
{ | |
v27 = 0.0; | |
v28 = v49; | |
v3 = v47 - v3; | |
} | |
else | |
{ | |
v28 = v49; | |
if ( v21 & 5 ) | |
{ | |
v27 = v44 - v4; | |
v3 = 0.0; | |
} | |
else | |
{ | |
v3 = CGPointZero[0]; | |
v27 = CGPointZero[1]; | |
} | |
} | |
-[UIPanGestureRecognizer setTranslation:inView:](self, "setTranslation:inView:", v28, v3, v27); | |
} | |
else if ( (unsigned __int8)-[UIScrollViewPanGestureRecognizer _shouldContinueToWaitToTransferTrackingFromParentScrollView]( | |
self, | |
"_shouldContinueToWaitToTransferTrackingFromParentScrollView") | |
|| (*((_BYTE *)self + 432) &= 0x7Fu, | |
v40 = self, | |
v41.dummy = &OBJC_CLASS___UIScrollViewPanGestureRecognizer, | |
!(unsigned __int8)objc_msgSendSuper2(&v40, "_shouldTryToBeginWithEvent:", v48)) ) | |
{ | |
LABEL_57: | |
objc_release(v45); | |
LABEL_12: | |
v9 = 0; | |
event = v48; | |
v13 = v49; | |
LABEL_13: | |
objc_release(v13); | |
goto LABEL_14; | |
} | |
} | |
v29 = v49; | |
if ( (unsigned __int8)objc_msgSend(v49, "isPagingEnabled") ) | |
v21 = (__int64)objc_msgSend(v29, "_abuttedPagingEdges"); | |
v46 = v21; | |
LOBYTE(v44) = (unsigned __int64)objc_msgSend(v29, "_canScrollX"); | |
LOBYTE(v47) = (unsigned __int64)objc_msgSend(v29, "_canScrollY"); | |
v30 = v45; | |
if ( (unsigned __int8)objc_msgSend(v45, "_canScrollX") ) | |
v31 = (unsigned __int8)objc_msgSend(v30, "isScrollEnabled") == 0; | |
else | |
v31 = 1; | |
if ( (unsigned __int8)objc_msgSend(v30, "_canScrollY") ) | |
v34 = (unsigned __int8)objc_msgSend(v30, "isScrollEnabled") != 0; | |
else | |
LODWORD(v34) = 0; | |
v35 = v46; | |
LOBYTE(v33) = v31 || v50 != 0 && LOBYTE(v47) != 0; | |
v36 = (v31 || v50 != 0 && LOBYTE(v47) != 0) == 0; | |
v37 = LOBYTE(v44); | |
if ( !v36 | |
|| LOBYTE(v44) | |
&& ((-[UIScrollViewPanGestureRecognizer _hysteresis](self, "_hysteresis", v32, v33), !(v35 & 2)) || v42 < v3) | |
&& ((-[UIScrollViewPanGestureRecognizer _hysteresis](self, "_hysteresis"), !(v35 & 8)) || (v3 = -v3, v3 < v42)) ) | |
{ | |
if ( v37 != 0 && v51 != 0 || !(_DWORD)v34 ) | |
goto LABEL_50; | |
if ( LOBYTE(v47) ) | |
{ | |
-[UIScrollViewPanGestureRecognizer _hysteresis](self, "_hysteresis"); | |
if ( !(v35 & 1) || v43 < v3 ) | |
{ | |
-[UIScrollViewPanGestureRecognizer _hysteresis](self, "_hysteresis"); | |
if ( !(v35 & 4) || -v3 < v43 ) | |
goto LABEL_50; | |
} | |
} | |
} | |
goto LABEL_57; | |
} | |
v9 = 0; | |
LABEL_14: | |
objc_release(event); | |
return v9; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void __cdecl -[UIScrollViewPanGestureRecognizer touchesBegan:withEvent:](UIScrollViewPanGestureRecognizer *self, SEL a2, id a3, id a4) | |
{ | |
id v4; // r14 | |
__int64 v5; // r15 | |
void *v6; // r14 | |
unsigned __int64 v7; // r12 | |
UIScrollViewPanGestureRecognizer *v8; // [rsp+0h] [rbp-30h] | |
__objc2_class *v9; // [rsp+8h] [rbp-28h] | |
v4 = a4; | |
v5 = objc_retain(a3); | |
v6 = (void *)objc_retain(v4); | |
v7 = self->super._lastTouchCount; | |
self->_modifierFlags = (signed __int64)objc_msgSend(v6, "_modifierFlags"); | |
v8 = self; | |
v9 = &OBJC_CLASS___UIScrollViewPanGestureRecognizer; | |
objc_msgSendSuper2(&v8, "touchesBegan:withEvent:", v5, v6, self, &OBJC_CLASS___UIScrollViewPanGestureRecognizer); | |
objc_release(v5); | |
if ( !v7 ) | |
-[UIScrollViewPanGestureRecognizer _beginScroll](self, "_beginScroll"); | |
*((_BYTE *)self + 432) &= 0xFCu; | |
if ( !-[UIGestureRecognizer state](self, "state") | |
&& (unsigned __int8)-[UIScrollViewPanGestureRecognizer _shouldTryToBeginWithEvent:]( | |
self, | |
"_shouldTryToBeginWithEvent:", | |
v6) ) | |
{ | |
-[UIPanGestureRecognizer _removeHysteresisFromTranslation](self, "_removeHysteresisFromTranslation"); | |
-[UIGestureRecognizer setState:](self, "setState:", 1LL); | |
} | |
objc_release(v6); | |
} |
真的强!顺便问下大佬的这套流程下来用的哪些工具
真的强!顺便问下大佬的这套流程下来用的哪些工具
- 伪代码: IDA
- 开发&调试: Xcode & lldb
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
疑问
A/B/C
: 放在UIScrollView
中B
在显示的时候,上下滑动B
内容会滚动,左右滑动时B
的父视图UIScrollView
会滚动疑问的重点来了: 系统究竟做了什么,这个操作竟然如此流畅?
初步定位
一个猜测: 要判定
UIScrollView
是否支持左右/上下
手势,只需要根据-[UIScrollView contentSize]
与-[UIScrollView frame].size
对比即可, 那么势必要访问-[UIScrollView contentSize]
, 则断点应该有现场于是得到如下信息
开始验证
乍一看,
-[UIScrollViewPanGestureRecognizer _canTransferTrackingFromParentPagingScrollView]
不就是我们需要的么?于是编写代码进行hook测试, 结果对流畅的拖拽并没有什么影响.失望.jpeg经过漫长的摸索, 定位到
-[UIScrollViewPanGestureRecognizer touchesBegan:withEvent:]
中的-[UIScrollViewPanGestureRecognizer _shouldTryToBeginWithEvent:]
函数,然后当该函数返回NO
的时候,该UIScrollView
则无法响应拖拽手势,便会通过-[UIScrollView _parentScrollView]
寻找可以响应的UIScrollView
. 开心.jpeg