背景知识:
Safari Web Content Guide中关于orientationchange的文档:
这里用addEventListener来实现:https://code.csdn.net/hursing/pagetest/blob/master/orientationchange.html
<html>
<head>
<title>orientationchange</title>
</head>
<body>
<p id="test">angle</p>
<script type="text/javascript">
function orientationHandler() {
var orientation = window.orientation;
switch (orientation) {
case 0:
case 90:
case -90:
case 180:
document.getElementById("test").innerHTML = orientation;
break;
default:
document.getElementById("test").innerHTML = "oh my god~";
break;
}
}
window.addEventListener("orientationchange", orientationHandler, false);
</script>
</body>
</html>
可以用iOS Safari或UIWebView来访问这个网页,旋转设备,会看到角度的实时变化。
orientationchange相关的逻辑由宏ENABLE_ORIENTATION_EVENTS包着,代码里的例子
DOMWindow.h:
#if ENABLE(ORIENTATION_EVENTS)
// This is the interface orientation in degrees. Some examples are:
// 0 is straight up; -90 is when the device is rotated 90 clockwise;
// 90 is when rotated counter clockwise.
int orientation() const;
DEFINE_ATTRIBUTE_EVENT_LISTENER(orientationchange);
#endif
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
函数。(识别方法请参考《
xcode反汇编调试iOS模拟器程序(四)自动断点应用之NSNotificationCenter》)
(lldb) po *(id*)($ebp+16)
$1 = 0x0082877c UIWindowDidRotateNotification
触发时的主线程堆栈:
Thread 1, Queue : com.apple.main-thread
#0 0x0278f730 in -[WebFrame(WebPrivate) sendOrientationChangeEvent:] ()
#1 0x001f1d65 in -[UIWebDocumentView sendOrientationEventForOrientation:] ()
#2 0x00207a7c in -[UIWebView _didRotate:] ()
#3 0x00bae4f9 in __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 ()
#4 0x01dbc0c5 in ___CFXNotificationPost_block_invoke_0 ()
#5 0x01d16efa in _CFXNotificationPost ()
#6 0x00ae2bb2 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#7 0x0006a863 in -[UIWindow _finishedFullRotation:finished:context:skipNotification:] ()
#8 0x0006a959 in -[UIWindow _finishedFullRotation:finished:context:] ()
#9 0x0006fd66 in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] ()
#10 0x0006ff04 in -[UIViewAnimationState animationDidStop:finished:] ()
#11 0x0235a7d8 in CA::Layer::run_animation_callbacks(void*) ()
#12 0x04ad8014 in _dispatch_client_callout ()
#13 0x04ac87d5 in _dispatch_main_queue_callback_4CF ()
#14 0x01d08af5 in __CFRunLoopRun ()
#15 0x01d07f44 in CFRunLoopRunSpecific ()
#16 0x01d07e1b in CFRunLoopRunInMode ()
#17 0x01cbc7e3 in GSEventRunModal ()
#18 0x01cbc668 in GSEventRun ()
#19 0x00031ffc in UIApplicationMain ()
#20 0x00001eb2 in main at /Users/liuhx/Desktop/UIWebView_Research/WebViewResearch/main.mm:16
在0层函数里使用GCD技术,让一个block函数到WebThread里执行。随后WebThread的堆栈为:
Thread 5 WebThread, Queue : (null)
#0 0x02c46030 in WebCore::Frame::sendOrientationChangeEvent(int) ()
#1 0x0278f7cc in __51-[WebFrame(WebPrivate) sendOrientationChangeEvent:]_block_invoke_0 ()
#2 0x0363a548 in HandleRunSource ()
#3 0x01ce5f3f in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
#4 0x01ce596f in __CFRunLoopDoSources0 ()
#5 0x01d08734 in __CFRunLoopRun ()
#6 0x01d07f44 in CFRunLoopRunSpecific ()
#7 0x01d07e1b in CFRunLoopRunInMode ()
#8 0x03639c50 in RunWebThread(void*) ()
#9 0x9854aed9 in _pthread_start ()
至此开始有开源码了:
#if ENABLE(ORIENTATION_EVENTS)
void Frame::sendOrientationChangeEvent(int orientation)
{
m_orientation = orientation;
if (Document* doc = document())
doc->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false));
}
#endif // ENABLE(ORIENTATION_EVENTS)
总之,orientationchange事件的传递路径为:
UIKit::UIWebView->UIKit::UIWebDocumentView->WebKit::WebFrame--block函数跨线程-->WebCore::Frame
剩下的工作就是WebCore::EventTarget的标准流程了。
MobileSafari是不用UIWebView的,直接由UIViewController把事件传给UIWebDocumentView,但是路径并不同。堆栈如下:
Thread 1, Queue : com.apple.main-thread
#0 0x04487730 in -[WebFrame(WebPrivate) sendOrientationChangeEvent:] ()
#1 0x01e70d65 in -[UIWebDocumentView sendOrientationEventForOrientation:] ()
#2 0x0002d6f8 in ___lldb_unnamed_function816$$MobileSafari ()
#3 0x0002e006 in ___lldb_unnamed_function824$$MobileSafari ()
#4 0x01e681cf in -[UIWebDocumentView setFrame:] ()
#5 0x020741d0 in -[UIWebBrowserView setFrame:] ()
#6 0x01e69967 in -[UIWebDocumentView _updateSize] ()
#7 0x01e6b516 in -[UIWebDocumentView _WAKViewSizeDidChange:] ()
#8 0x00ba74f9 in __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 ()
#9 0x004e50c5 in ___CFXNotificationPost_block_invoke_0 ()
#10 0x0043fefa in _CFXNotificationPost ()
#11 0x00adbbb2 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#12 0x0047f1bd in __invoking___ ()
#13 0x0047f0d6 in -[NSInvocation invoke] ()
#14 0x03556dc3 in SendMessage(NSInvocation*) ()
#15 0x03555967 in SendDelegateMessage(NSInvocation*) ()
#16 0x0354cc51 in notificationCallback(WKView*, WKViewNotificationType, void*) ()
#17 0x035a0c49 in WKViewSetBoundsSize ()
#18 0x0354d8d5 in -[WAKView setBoundsSize:] ()
#19 0x033433c5 in WebCore::ScrollView::platformSetContentsSize() ()
#20 0x0333fd0e in WebCore::ScrollView::setContentsSize(WebCore::IntSize const&) ()
#21 0x02b98eb5 in WebCore::FrameView::setContentsSize(WebCore::IntSize const&) ()
#22 0x02b98fcc in WebCore::FrameView::adjustViewSize() ()
#23 0x02b9a56d in WebCore::FrameView::layout(bool) ()
#24 0x02ba0a8c in WebCore::FrameView::forceLayout(bool) ()
#25 0x044b77e7 in -[WebHTMLView layoutToMinimumPageWidth:height:originalPageWidth:originalPageHeight:maximumShrinkRatio:adjustingViewSize:] ()
#26 0x044b7851 in -[WebHTMLView layout] ()
#27 0x01e68ff6 in -[UIWebDocumentView viewportConfigurationsDidChange:] ()
#28 0x01e6b6ec in -[UIWebDocumentView setMinimumSize:updateCurrentViewportConfigurationSize:] ()
#29 0x01e6b5de in -[UIWebDocumentView setMinimumSize:] ()
#30 0x0002d6d6 in ___lldb_unnamed_function816$$MobileSafari ()
#31 0x0003b49b in ___lldb_unnamed_function1040$$MobileSafari ()
#32 0x0003b337 in ___lldb_unnamed_function1039$$MobileSafari ()
#33 0x00049b52 in ___lldb_unnamed_function1308$$MobileSafari ()
#34 0x01da06aa in -[UIViewController _didRotateFromInterfaceOrientation:forwardToChildControllers:skipSelf:] ()
#35 0x01da0bb7 in -[UIViewController window:didRotateFromInterfaceOrientation:] ()
#36 0x01ce96ee in -[UIWindow _finishedFullRotation:finished:context:skipNotification:] ()
#37 0x01ce9959 in -[UIWindow _finishedFullRotation:finished:context:] ()
#38 0x01ceed66 in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] ()
#39 0x01ceef04 in -[UIViewAnimationState animationDidStop:finished:] ()
#40 0x01b087d8 in CA::Layer::run_animation_callbacks(void*) ()
#41 0x04ce7014 in _dispatch_client_callout ()
#42 0x04cd77d5 in _dispatch_main_queue_callback_4CF ()
#43 0x00431af5 in __CFRunLoopRun ()
#44 0x00430f44 in CFRunLoopRunSpecific ()
#45 0x00430e1b in CFRunLoopRunInMode ()
#46 0x00ec07e3 in GSEventRunModal ()
#47 0x00ec0668 in GSEventRun ()
#48 0x01cb0ffc in UIApplicationMain ()
#49 0x0005be87 in ___lldb_unnamed_function1676$$MobileSafari ()
其中几行___lldb_unnamed_function应该是Safari的C++代码,去掉了符号表,不清楚是什么,还是不能肯定地说MobileSafari一定是viewport改变后才改变设备方向。
只好说,使用UIWebView的第三方浏览器想跟Safari比效率?还是算了吧。
转载请注明出处:http://blog.csdn.net/hursing