그렇다면 동기화 인터페이스를 js 레이어로 내보내는 방법은 무엇입니까?
Android 프레임워크에서 Java 인터페이스는 함수 WebView.addJavascriptInterface () 를 통해 js 레이어로 내보낼 수 있으므로 내보낸 인터페이스가 동기화 인터페이스입니다. 그러나 iOS 의 COA 프레임워크에서는 동기화 인터페이스를 내보내는 것이 쉽지 않습니다. UIWebView 와 WKWebView 에는 addJavascriptInterface 기능이 없기 때문입니다. 동시에 Android 의 기능에도 보안 취약점이 생겼다. 그럼, 동기화 호출을 할 수 있는 다른 방법이 있나요? IOS UIWebView 를 예로 들자면, WKWebView 와 Android 도 참고할 수 있습니다.
문제의 핵심을 찾기 위해 iOS 에서 js 호출 app 를 구현하는 일반적인 방법을 살펴보겠습니다.
먼저 UIWebViewDelegate 를 사용자 정의하고 shouldstartloadwithrequest: navigationtype 함수에서 다음을 수행합니다.
1
2
셋;삼;3
사
다섯;오;5
여섯;육
일곱
여덟;팔
아홉;구;9
10
1 1
12
13
14
15
16
-(bool) webview: (ui webview * _ nonnull) webview
Shouldstartloadwithrequest: (nsurlrequest * _ nonnull) 요청
Navigationtype: (uiwebviewnavigationtype) navigationtype {
만약 ([요청]. Http method compare: @ "get" options: nscaseinsensitivesearch]! = NSOrderedSame) {
//비 get 요청을 처리하지 않습니다.
YES 를 반환합니다
}
NSURL* URL = 요청. 웹 사이트
If ([url.scheme is equal tostring: @' yourcustomprotocol']) {
Return [self on my request: request];
}
YES 를 반환합니다
}
이 메서드는 기본적으로 함수 호출 명령을 URL 로 변환하여 요청 시 app 계층에 알리는 것입니다. 여기서 onMyRequest: 는 사용자 정의 요청 응답 함수입니다. 요청을 보내기 위해 js 계층은 숨겨진 iframe 요소를 만들고 요청을 보낼 때마다 iframe 요소의 src 속성을 수정하여 app 가 해당 요청을 차단할 수 있도록 합니다.
1
2
셋;삼;3
사
다섯;오;5
여섯;육
일곱
여덟;팔
아홉;구;9
10
1 1
12
13
/* *
* js 는 네이티브에 메시지를 전달합니다.
* @ methodjs _ sendmessagetonativasync
* @ member of jstonativeiospolyfill
* @public
* @param str {String} 메시지 문자열, HybridMessage 에서 변환됨.
*/
Jstonativeiospolyfill.prototype.js _ sendmessagetonativeasync = function (str) {
만약 (! This.ifr_) {
이것. _ prepareifr ();
}
This.ifr_. Src =' yourcustomprotocol://_ _ _ message _ send _ _? Msg = '+encodeURIComponent(str); (str); }
App 가 js 호출의 함수를 실행할 때 실행 결과를 직접 반환할 수 없습니다. 결과를 반환하기 위해 일반적으로 콜백 함수인 ——JS 레이어를 사용하여 콜백을 기록합니다. app 는 jsonp 와 유사한 메커니즘인 UIWebView 의 Stringbyevaluationjavascriptfromstring 함수를 통해 이 콜백을 호출합니다.
이런 방식으로 캡슐화된 인터페이스는 당연히 비동기적입니다. 함수 js _ sendMessageToNativeAsync 는 실행 결과가 반환될 때까지 기다리지 않고 즉시 반환하기 때문입니다.
따라서 js 코드를 "차폐" 하는 방법을 찾아야합니다.
Js 에서 어떤 방법으로 CPU 를 가득 채우지 않고 UI 스레드 코드를 "차단" 할 수 있는지 생각해 보십시오.
1
2
셋;삼;3
사
Var async = false
Var URL = \ "\";
Var 메서드 =' get & ltbr & gt var req = new xmlhttprequest (); & ltbr & gt
Req.open (메소드, URL, 비동기); & ltbr & gtreq.send (비어 있음);
"동기" Ajax (사실 이 단어가 없고, Ajax 는 비동기를 의미함) 네! 이 코드는 바이두의 응답이 반환될 때까지 계속 차단될 것이다. 일반적으로 동기화 요청은 허용되지 않으며 이로 인해 UI 카튼의 위험이 발생할 수 있습니다. 하지만 여기서, 우리가 실제로 원격으로 내용을 요청하지 않기 때문에, 우리는 그것을 사용할 수 있습니다.
지금까지 구현 방법이 비교적 명확해졌으니, 이제 생각을 정리해 보겠습니다.
XMLHttpRequest 와 특별히 구성된 URL 을 동기화하여 응용 프로그램 계층에 알립니다.
애플리케이션 계층은 함수 실행 요청을 가로채고 결과를 응답으로 반환합니다.
XMLHttpRequest.send () 는 status 및 responseText 를 통해 결과를 반환합니다.
그럼 어떻게 요청을 가로막을까요? UIWebViewDelegate 는 XMLHttpRequest 요청을 가로채지 않는 것으로 알려져 있지만, iOS 는 최소한 ——Nsurlcache 와 NSURLProtocol 의 두 가지 요청을 가로막는 장소를 제공합니다.
1.NSURLCache 는 iOS 에서 사용자 정의 캐시를 구현하는 클래스입니다. 사용자 정의 NSURLCache 하위 클래스 객체를 만들어 글로벌 캐시 관리자로 설정하면 모든 요청이 먼저 여기에 도착하여 캐시를 금지하지 않는 경우 캐시가 있는지 확인합니다. 이 속성을 사용하여 인터페이스 호출 요청을 가로채고 데이터를 실행 및 반환할 수 있습니다.
1
2
셋;삼;3
사
다섯;오;5
여섯;육
일곱
여덟;팔
아홉;구;9
10
1 1
12
13
14
15
16
17
18
19
20
2 1
22
23
24
25
26
-(nscachedurlresponse *) cachedresponseforrequest: (nsurlrequest *) request {
만약 ([요청]. Http method compare: @ "get" options: nscaseinsensitivesearch]! = NSOrderedSame) {
//get 요청만 사용자 정의합니다.
Return [supercachedresponseforrequest: request];
}
NSURL* URL = 요청. 웹 사이트
NSString * path = url.path
NSString * query = url.query
If (path == nil || query == nil) {
Return [supercachedresponseforrequest: request];
}
LOGF(@"url = %@, 경로 =% @, 쿼리 =% @ ",URL, 경로, 쿼리);
If ([경로 is equal tostring: @ "_ _ env _ get _ _"]) {
//환경 변수 읽기
Return [self getenvvaluebyurl: URL]; //*
} elseif ([path is equal tostring: @ "_ _ env _ set _ _"]) {
//쓰기 환경 변수
Return [self setenvvaluebyurl: URL];
}
Return [supercachedresponseforrequest: request];
}
주의 * 줄은 app 인터페이스를 실행하여 결과를 반환하는 것입니다. 여기 결과는 NSCachedResponse 대상이기 때문에 군더더기는 하지 않겠습니다.