ios | ios도 모르고 하이브리드 앱 개발하기 [ 11 webview와 javascript간의 상호 호출하기 ]

2016. 9. 19. 14:54mobile/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에 무지한 상태에서 구글링만으로 앱 개발 및 포스팅이 진행됨


누구나 따라할 수 있겠지만 결코 완벽한 정답이 아닐 수 있음


아주 주관적인 입장에서의 포스팅임