2016. 9. 19. 14:54ㆍmobile/ios
ios도 모르고 하이브리드 앱 개발하기 [ 11 webview와 javascript간의 상호 호출하기 ]
하이브리드 앱을 만들면 네이티브 부분과 web 부분이 서로 통신할 경우가 생긴다.
ios 앱에서 javascript 를 호출하거나
반대로 javascript 에서 ios 를 호출할 경우가 있다.
이를 구현하기 위해서는 우선 Delegate를 사용해야 한다.
Delegate 는 어떤 클래스의 함수를 대신 구현하겠다는 의미이다.
UIWebView의 Delegate를 선언해서 webview 가 실행되기 전에 url을 캐치해서 webview와 javascript 간의 상호 호출하는 부분을 구현해야 한다.
android와 비교하면 WebViewClient 를 상속받은 클래스를 하나 생성하고 shouldOverrideUrlLoading 메소드를 Override 하는 개념이 아닐까 생각해 본다.
ViewController.h 파일
UIWebViewDelegate를 선언하자.
1
2
3
4
5
6
7 |
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController<UIWebViewDelegate>
@property (weak, nonatomic) IBOutlet UIWebView *webView;
- (void) printAlert:(NSString*)title msg:(NSString*)msg;
- (BOOL) isConnectedNetwork;
@end |
cs |
3# 마지막 부분(글자배경색 파란 부분)을 위와 같이 수정한다.
ViewController.m 파일
선언된 UIWebViewDelegate의 함수를 대신 사용하겠다고 알려주어야 한다.
viewDidLoad 함수 내부에 다음과 같이 선언해주면 된다.
1 |
_webView.delegate = self; |
cs |
그리고 함수를 작성한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 |
// webView start load
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *requestStr = [[request URL] absoluteString];
// web 에서 app 호출 시 특정 url로 판단하고 이벤트 실행함
if ([[[request URL] absoluteString] hasPrefix:@"appschemeios:"]) {
NSString *requestString = [[request URL] absoluteString];
NSArray *components = [requestString componentsSeparatedByString:@":?:"];
NSArray *functionStrArr = [[components objectAtIndex:1] componentsSeparatedByString:@":::"];
NSString *functionName = [functionStrArr objectAtIndex:0];
NSString *functionParam = [functionStrArr objectAtIndex:1];
NSString *functionParam2 = [functionStrArr objectAtIndex:2];
// 함수 구분
if([functionName isEqualToString:@"helloFn"]){
if([functionParam isEqualToString:@"ios"]){
[self printAlert:@"Web Message" msg:functionParam2];
}else if([functionParam isEqualToString:@"javascript"]){
// javascript 호출
[_webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"hiFunction(\"%@\");",@"hi javascript"]];
}
}
return NO;
} else{
return YES;
}
} |
cs |
2# : web view가 url을 실행하기 전에 실행되는 함수
4# : url을 가져온다.
8# : appschemeios: 라는 문자열이 들어있는지 체크, 들어있다면 네이티브를 호출했다고 판단함
9# ~ 14# : 미리 정의된 문자열을 역할에 맞게 분류함
나는 appschemeios:?:function:::param1:::param2 이런 식으로 javascript에서 호출함
고로 :?: 문자열 뒷부분으로 첫번째가 함수, 두번째는 파라미터1, 세번째는 파라미터2 순서임 (정의하기 나름)
17# : helloFn 이라는 함수명이 있는지 체크
18# : 첫번째 파라미터가 네이티브를 호출할 것인지 javascript를 호출할 것인지에 대한 구분 flag값임
ios 이면 네이티브 alert 호출, javascript 이면 javascript 함수 호출
22# : javascript 호출하는 부분
함수명은 hiFunction 이고 파라미터 1개 받음
이 부분은 별도로 ios 네이티브에서 특정 이벤트 발생 시 사용해도 무방하다. 꼭 shouldStartLoadWithRequest 내부에 있을 필요가 없다.
index.jsp 파일
마지막으로 webproject에서 javascript 부분을 수정해야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 |
<body>
헬로 jsp
<script>
function helloClick(){
var type = document.getElementById('type').value;
var msg = document.getElementById('msg').value;
location.href = "appschemeios:?:helloFn:::"+type+":::"+msg;
}
function hiFunction(msg){
alert(msg);
}
</script>
<input type="text" id="type" value="ios">
<input type="text" id="msg">
<input type="button" value="클릭" onclick="helloClick()">
</body> |
cs |
4# : 웹에서 버튼으로 실행할 함수, IOS 를 호출함
10# : IOS 에서 실행시킬 함수
14# : IOS에서 구분할 type flag (ios 또는 javascript)
type 과 msg 의 값을 달리 주면서 실행해보면 원리가 금방 이해되리라 생각된다.
* 경고 IOS에 무지한 상태에서 구글링만으로 앱 개발 및 포스팅이 진행됨 누구나 따라할 수 있겠지만 결코 완벽한 정답이 아닐 수 있음 아주 주관적인 입장에서의 포스팅임 |