当用到UIWebView、UITextField、UITextView等类时,就会看到WebThread线程:
在lldb中搜索
(lldb) image lookup -r -s [wW]ebThread
会有超过一百个结果。
对于普通开发者而言,WebThread最有意义的东西恐怕是UIWebView的私有API
- (void)_setDrawInWebThread:(BOOL)drawInWebThread;
设置YES后,会在WebThread进行渲染的某些操作(layoutTiles),不占用主线程。
Mac上的Safari是多进程程序,排版和渲染等是在独立的进程里。iOS不允许多进程,只有多线程,所以在iOS版的WebCore.framework里会有一些代码来把多进程机制适配成多线程机制,WebThread就是主要产物之一。
iOS的WebCore开源码,6.1版本的下载地址为:http://opensource.apple.com/release/ios-61/
比起webkit.org上的Mac开源码,会多了个wak目录,内有21个文件,其中与WebCoreThread相关的有6个。常见的被调用函数有这么一些:
// The lock is automatically freed at the bottom of the runloop. No need to unlock. // Note that calling this function may hang your UI for several seconds. Don't use // unless you have to. void WebThreadLock(void); // This is a no-op for compatibility only. It will go away. Please don't use. void WebThreadUnlock(void); // Please don't use anything below this line unless you know what you are doing. If unsure, ask. // --------------------------------------------------------------------------------------------- bool WebThreadIsLocked(void); bool WebThreadIsLockedOrDisabled(void); void WebThreadLockPushModal(void); void WebThreadLockPopModal(void); void WebThreadEnable(void); bool WebThreadIsEnabled(void); bool WebThreadIsCurrent(void); bool WebThreadNotCurrent(void); // These are for <rdar://problem/6817341> Many apps crashing calling -[UIFieldEditor text] in secondary thread // Don't use them to solve any random problems you might have. void WebThreadLockFromAnyThread(); void WebThreadLockFromAnyThreadNoLog(); void WebThreadUnlockFromAnyThread();
// // Release an object on the main thread. // @interface NSObject(WebCoreThreadAdditions) - (void)releaseOnMainThread; @end // Register a class for deallocation on the WebThread void WebCoreObjCDeallocOnWebThread(Class cls); void WebCoreObjCDeallocWithWebThreadLock(Class cls); // Asynchronous from main thread to web thread. void WebThreadCallAPI(NSInvocation *invocation); /* DEPRECATED; use WebThreadRun() in WebCoreThreadRun.h */ void WebThreadAdoptAndRelease(id obj); // Synchronous from web thread to main thread, or main thread to main thread. void WebThreadCallDelegate(NSInvocation *invocation); void WebThreadRunOnMainThread(void (^)(void)); // Asynchronous from web thread to main thread, but synchronous when called on the main thread. void WebThreadCallDelegateAsync(NSInvocation *invocation); // Asynchronous from web thread to main thread, but synchronous when called on the main thread. void WebThreadPostNotification(NSString *name, id object, id userInfo); // Convenience method for making an NSInvocation object NSInvocation *WebThreadMakeNSInvocation(id target, SEL selector);
UIKit只工作在main thread,WebCore工作在WebThread,当产生交集时就需要线程间通信,以上函数就是为了线程间消息服务的,最多的操作当然就是加锁了。具体的发消息实现有几种,RunLoop、GCD、performSelector、pthread都会用,也可谓复杂了。依我看应该是新老技术替换的结果,说不定还是新老员工的不同工作结果。
WebThread是以pthread创建的,有全局变量pthread_t webThread来做引用,在不少地方会有
pthread_equal(pthread_self(), webThread)
的判断。
模态机制用的是CFRunLoop。异步消息多用GCD。
在WebView和Clients间通信时,有两个类作为消息中转,_WebSafeForwarder和_WebSafeAsyncForwarder。
让人纠结的是,iOS的实现是在把单线程的Mac上的WebKit.framework改成多线程,但又没法用类似WebKit2.framework的那种多进程方案。WebKit.framework里诸多的WebHTMLView是会直接访问WebCore的,所以iOS上的WebKit.framework里多了好多的锁。为了避免被developer吐槽,这个框架就干脆不公开了,用UIWebView封装好,只有那几个简单的接口来做门面。