背景知识:
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