출처: http://egloos.zum.com/saveworld/v/2828855
이 글은 아래에 링크 걸려있는 블로그의 내용을 번역한 내용입니다.
この文書は下のリンク先のブログの内容を翻訳したものです。
http://niw.at/articles/2009/02/06/how-to-enable-the-popup-window-on-uiwebview/ja
번역이 매끄럽지 못한 점, 죄송합니다..;;
UIWebView는 iPhone SDK에서 꽤 중요한 UIKit 클래스입니다.
알고 계신대로 사파리가 통째로 들어있지만, 윈도우를 열거나 팝업 등의 이벤트는 처리되지 않도록 되어 있습니다.
<a href="somehere" target="_blank" />Open this link in new window</a>
예를 들면, 이러한 링크가 UIWebView 안에 표시되어 유저가 클릭했다고 해도 아무런 동작을 하지 않습니다.
물론, UIWebView는 상당히 고도로 추상화되어 있고, 몇가지 메소드를 호출하는 것은 가능합니다.
그래서 완벽하지는 않지만 어느정도 이 문제를 해결 할 방법을 제공합니다. 열쇠가 되는 메소드는 다음과 같습니다.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
- (void)webViewDidFinishLoad:(UIWebView *)webView
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
모든 팝업 윈도우를 가로채기
먼저 표시하고 있는 웹페이지의 모든 윈도우를 여는 이벤트를 가로챕니다. 방법은 JavaS-ript로 해결합니다.
먼저 모든 새 윈도우 열기 이벤트를 가로채서 열어야하는 URL을 특정화 하고, 그곳에 Objective-C 쪽에서 그 특정화 한 URL을 재처리하여
자신이 윈도우를 엽니다.
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[webView stringByEvaluatingJavaScriptFromString:/* JavaScriptの入った文字列 */];
}
다음의 JavaScript를 stringByEvaluatingJavaScriptFromString에 넘깁니다.
var tags = document.getElementsByTagName("a");
for(var i=0; i < tags.length; i++) {
var tag = tags[i];
var t = tag.getAttribute("target");
var h = tag.getAttribute("href");
if(/* targetとhrefを確認 */) {
tag.setAttribute("target", "");
tag.setAttribute("href", /* href属性から特別なURLを作成 */);
}
}
webViewDidFinishLoad가 호출되었을 때에 JavaScript를 샐행하여 모든 anchor 태그를 가로채어 타겟 속성을 삭제하고
href에 특정화 시킨 URL으로 치환합니다. 다시 폼과 JavaScript로부터 이벤트를 가로챕니다.
var tags = document.getElementsByTagName("form");
for(var i=0; i < tags.length; i++) {
var tag = tags[i];
var submit = tag.submit;
tag.submit = function() {
var t = tag.target;
var a = tag.action;
if(/* targetとactionを確認 */) {
tag.target = "";
tag.action = /* action属性から特別なURLを作成 */
}
return submit.apply(this, arguments);
};
}
このコードは多くの状況で動くのですが、すべての状況での動作は難しいです。特にsumitイベントのリスナーが存在する場合などです。
window.open = function(url) {
if(/* urlを確認 */) {
var t = document.createElement("a");
t.setAttribute("href", /* 特別なurlを作成 */);
var e = document.createEvent("MouseEvent");
e.initMouseEvent("click");
t.dispatchEvent(e);
}
};
이 코드는 상당히 이상한 코드입니다.
window.open이 호출 될 때에 화면 뒤 쪽에서 보이지 않는 anchor 태그를 만들어 그것에 특별한 URL을 설정하여 HTTP Request를 발생시킵니다.
이 Request를 Objective-C 쪽에서 받습니다.
팝업 이벤트를 Objective-C에서 받기
이것으로 Objective-C 쪽에서 이벤트를 받을 수 있게 되었습니다. UIWebView의 delegate에서 팝업 이벤트를 받아 처리합니다.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if(navigationType == UIWebViewNavigationTypeLinkClicked || navigationType == UIWebViewNavigationTypeFormSubmitted) {
NSURL *url = [request URL];
if(/* URLが特別なものか確認 */) {
NSString *urlstr = /* 特別なURLから普通のURLに戻す */;
NSMutableURLRequest *req = [request mutableCopyWithZone:nil];
[req setURL:[NSURL URLWithString:urlstr]];
if(/* ポップアップは閉じているか? */) {
/* ポップアップを開く */
}
[popupWebView loadRequest:req];
return NO;
}
}
return YES;
}
이 아주 긴 이름의 delegate로 모든 HTTP Request를 취득할 수 있습니다. 먼저 Request의 URL가 JavaScript로 만든 특정화 시킨 것인가를 체크하여
만약 그렇다면 보통의 URL을 반환하여 NSURLRequest를 작성하고, 팝업으로 띄울 UIWebView로 넘깁니다. 이 들 코드에 의해서 UIWebView로 팝업을
구현할 수 있습니다.
특별한 URL을 작성
이 문제는 조금 어렵습니다. 왜냐하면, HTTP Request의 베이스 URL을 보유하고 있을 필요가 있기 때문입니다.
URL을 바꿔 쓰더라도 안전한 부분, 예를 들면 스키마나 호스트명 등입니다만, 이것들을 바꿔쓰면 베이스 URL을 잃어버려
webView:shouldStartLoadWithRequest:navigationType에서 팝업을 위한 URL을 작성할 수 없게 되버립니다.
그렇기 때문에 한가지 대안으로 URL의 마지막에 특별한 Hash를 부여하는 것으로 일단 해결해보겠습니다.
그다지 안전하지는 않지만 대부분의 상황에서는 안전합니다.
function makeSpecialURL(url) {
return url + (url.match(/#/) ? "_open" : "#open");
}
그리고 webView:shouldStartLoadWithRequest:navigationType에서 추가한 Hash를 삭제합니다.
if([[url fragment] hasSuffix:@"open"]) {
NSString *urlstr = [[url absoluteString] substringToIndex:[[url absoluteString] length] - 5];
...
}
그 밖의 방법에 대해서
이 문제는 아마도 문서에 포함되지 않은 API나 delegate(webView:createWebViewWithRequest:)로 해결 할 수 있을겁니다.
하지만 iPhone SDK에서는 이 JavaScript를 사용하는 방법 이외에는 해결 방법이 없겠지요. 별로 좋은 구현방법은 아니지만,
iPhone 어플리케이션 제작에 도움이 되면 좋겠다고 생각합니다.
출처 : http://passion818.tistory.com/entry/팝업-윈도우를-UIWebView에서-사용하기
'IT_Programming > Objective-C · Swift · iOS' 카테고리의 다른 글
[펌] 이펙티브 오브젝티브씨 | Effective Objective-c (0) | 2014.09.10 |
---|---|
[iOS] App 이름 지역화하기. (0) | 2014.03.26 |
[iOS] 다국어 스트링 지원하기 (0) | 2014.03.26 |
[iOS] 기기별 아이콘 이미지 처리 (0) | 2014.03.26 |
[펌] iPhone에서 하이브리드 앱 개발을 위해 Javascript와 Objective-C의 상호 호출하는 방법 (0) | 2013.02.01 |