2015-05-01 34 views
1

我有一個webView覆蓋- hitTest:的子類基本思想是,我想單擊webView傳遞到nextResponder如果點擊是在身體的DOM元素。該方法是這樣的異常崩潰與可可webView -elementAtPoint:(操作系統X)

- (NSView *)hitTest:(NSPoint)aPoint 
{ 
    NSDictionary *dict = [self elementAtPoint:aPoint]; 
    if([[dict valueForKey:@"WebElementDOMNode"] isKindOfClass:[DOMHTMLBodyElement class]]) 
    { 
     return (NSView *)[self nextResponder]; 
    } 

    return [super hitTest:aPoint]; 
} 

運行時,它與EXC_BAD_ACCESS code=2

崩潰的elementAtPoint現在,它變得怪異。如果我在該行斷開應用程序,並在LLDB中執行po [self elementAtPoint:aPoint],則LLDB會掛起,直到我執行^ C。

還沒有。如果我註釋掉除最後一個回報以外的所有內容,請打開return語句,然後在LLDB中運行po [self elementAtPoint:aPoint]-我得到了我期望的結果,一個很好的詞典告訴了我關於DOM的所有信息。

什麼可能導致此行爲?

注意:這是在OS X上,而不是在iOS上。

回答

0

什麼可能導致此行爲?

只需在WebKit source code中查看[WebView _elementAtWindowPoint:][WebView _frameViewAtWindowPoint:]實現。不幸的是,他們使用hitTest:來確定elementAtPoint:

在我而言,這種解決方法似乎工作:

- (NSView *)hitTest:(NSPoint)point 
{ 
    if (m_hitTestEnabled) 
    { 
     [NSTimer scheduledTimerWithTimeInterval:0. 
             target:self 
             selector:@selector(hitTestDelayed:) 
             userInfo:@[ @(point.x), @(point.y) ] 
             repeats:NO]; 
    } 
    return [super hitTest:point]; 
} 

- (void)hitTestDelayed:(NSTimer *)timer 
{ 
    NSPoint point = NSMakePoint([[timer userInfo][0] floatValue], [[timer userInfo][1] floatValue]); 

    m_hitTestEnabled = false; 
    NSDictionary *dict = [self elementAtPoint:point]; 
    m_hitTestEnabled = true; 

    if ([[dict valueForKey:@"WebElementDOMNode"] isKindOfClass:[DOMHTMLDivElement class]]) 
    { 
     NSLog(@"divAtPoint: %@", dict); 
    } 
} 

m_hitTestEnabledinitWith...方法設置爲YES

爲什麼使用計時器? WebView上的這些操作只能在主線程中使用。因此,我們無法啓動另一個線程來獲取elementAtPoint:並等待其在「主」hitTest:中完成。也許有人會想出更好的解決方案。

相關問題