2014-05-15 1 views
0

내 질문의 "in iOS 7"부분에 중복 된 것이 아니며 이전의 행동 (따라서 이전 질문에 대한 답변)이 변경되었습니다.iOS 7의 UIWebView 내에서 JavaScript에서 Objective-C를 호출하는 방법은 무엇입니까?

UIWebView를 통해 호출 된 JavaScript 코드가 iOS 7에서 Objective-C 코드를 호출 할 수있는 방법을 알고 싶습니다. 이전에 프로젝트에서 광범위하게 사용한 적이 있지만 iOS 7의 동작이 결과와 함께 변경되었습니다. 웹 뷰 위임자의 didFailLoadWithError가 이전에는 호출되지 않았을 때 호출됩니다.

function invokeObjectiveC(action, target, data) { 
    var iframe = document.createElement("IFRAME"); 
    iframe.setAttribute("src", "MY-URLScheme:" + action + ":" + target + ":" + data); 
    document.documentElement.appendChild(iframe); 
    iframe.parentNode.removeChild(iframe); 
    iframe = null; 
} 

didFailLoadWithError 일으키는 특정 라인 :

document.documentElement.appendChild(iframe); 

다른 일반적인 대안 : 전화를받을 수있는이 하나

나는 사용자 정의 URL 트릭을 사용하여 목표 - C 기능을 호출하는 데 사용 같은 일을하기 위해 인터넷 주위에 뿌려진 접근법은 다음과 같습니다.

window.location = "MY-URLScheme:" + action + ":" + target + ":" + data; 

그리고 didFailLoadWithError가 호출되지 않는다는 점에서 iOS 7에서 작동하지만, 두 번 연속 호출되면 첫 번째 호출이 손실된다는 (알려진) 문제가 있습니다.

그래서 나는 코르도바이를 어떻게하고 있는지 궁금 그래서 소스 코드를 다운로드보고했고 나는 그들이 이런 나에게 비슷한 일을 생각 (3 라인은 다릅니다) :

var iframe = document.createElement("IFRAME"); 
iframe.setAttribute("src", "MY-URLScheme:" + action + ":" + target + ":" + data); 
document.body.appendChild(iframe); 
iframe.parentNode.removeChild(iframe); 
iframe = null; 

그러나 여전히 didFailLoadWithError가 호출됩니다. 어느 날 코르도바가 (이 코드를 올바르게보고 있다고 가정하고) 이것을 바로 잡기 위해 아무 것도하지 않은 이유에 대해 의아해했습니다.

didFailLoadWithError가 호출되는 사실은 여전히 ​​페이지가로드되고 Objective-C가 여전히 호출되므로 detremental 인 것처럼 보이지 않습니다. 그러나 오류 메서드가 호출되어 결과적으로 다른 방법을 찾고 싶다는 코드를 갖는 것은 매우 불만족 스럽습니다.

그래서 질문 : UI가 안정적으로로드 된 JS 내에서 Objective-C를 호출하고 iOS 7에서 didFailLoadWithError가 호출되지 않는 이유는 무엇입니까?

누군가 Cordova가 위의 방법을 사용하고 있는지 확인할 수 있습니까?

JavaScriptCore를 UIWebView (UIWebView 외부와 반대)에서 사용하는 솔루션은 iOS/취약한 문서화되지 않은/지원되지 않는 모양으로 보입니까? 예를 들어 :

Access the JavaScriptCore engine of a UIWebView

Trigger objective C method from javascript using JavaScriptCore in iOS 7 in ViewControllers

답변

4

iframe이 해결 방법은 약간의 버그가 매우 신뢰할 수 없습니다. JavaScriptCore는 좋은 접근 방식이지만 프레임 워크는 iOS 6 및 iOS 5에서 비공개입니다. UIWebView에서 Objetive-C를 호출하는 더 빠르고 좋은 방법이 있습니다. 경고 기능에 대한 카테고리 메소드를 구현할 수 있습니다.

@implementation UIWebView (JavaScriptAlert) 
- (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame 
{ 
    if ([message hasPrefix:CUSTOM_SCHEME_STRING]) { 
     //process your message 
    } 
    else { 
     UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:message delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; 
     [alert show]; 
     [alert release]; 
    } 
} 
@end 

javascript에서 window.alert() 메서드를 호출하면 위의 Objetive-C 함수가 호출됩니다. 메시지에 사용자 지정 접두사를 사용하고 표준 경고를 원하면 UIAlertView로 대체하십시오.

이 방법은 iOS 5, 6 및 7에서 문제없이 작동합니다. 그것은 매우 신뢰할 수 있습니다. 나는 경보 10000 번을 연속적으로 발동 한 것을 시험하고 아무 메시지도 잃지 않는다. iframe 솔루션의 경우는 아니므로 iframe을 너무 빨리 작성하면 많은 메시지가 손실되므로 JS 코드에 배치 대기열을 구현하고 ~ 1ms 간격으로 동기화 할 수 있습니다.

+0

감사합니다. 시험해 보겠습니다. iOS 7에서만 실행중인 경우 JavaScriptCore 솔루션이 있습니까? – Gruntcakes

+0

@MortimerGoro 감사합니다. WebFrame 매개 변수가 무엇을 의미하는지 알고 싶습니다. 고맙습니다. –

+0

@MacGeek WebFrame 매개 변수는 runJavaScriptAlertPanelWithMessage 메서드의 서명에 있기 때문에 거기에 있습니다. 메서드 구현시이를 사용할 필요가 없습니다. 그냥 무시하십시오. – MortimerGoro