SMALL
iOS 에서의 Javascript Interface Bridge는 단방향, JS -> Native로밖에 값을 전달하지 못한다.
따라서 js에 setValue() 등의 함수를 사용해야 한다..
그러나 window.webkit.messageHandler.foo.postMessage(args) 를 호출하고, 네이티브에서 evalJavascript로 setFooValue(bar) 함수를 호출해 밸류를 지정해준다 한들, 완성된 js코드를 보는 후임 개발자 입장에서 코드가 쉽게 눈에 들어오지 않을 것이고, 예쁘지도 않다. 또 리턴받아야 하는 함수가 여러 개인 경우 setValue() 함수를 여러번 생성해야 하며, Android JavascriptInterface Bridge와 다른 방식으로 사용해야 한다.
안드로이드만큼 편하지는 않겠지만, 그래도 기존 방식보다 편하면서 간결하고, 안드로이드와 따로 호출하지 않아도 될만한 코드를 고민해봤다.
메인 js에 객체 생성
var nativeObj = {
coordinate:{
getFromNative: function(val){
if(nativeObj.nativeType.val == "Android"){
this.latitude = window.android.get_latitude();
this.longitude = window.android.get_longitude();
}else if(nativeObj.nativeType.val == "iOS"){
window.webkit.messageHandler.getCoordinate.postMessage("");
}else{
alert('앱에서만 이용이 가능한 기능입니다.');
}
},
latitude:0,
longitude:0
},
userToken: {
getFromNative: function(){
},
val:""
},
userState: false,
nativeType: {
get: function(){
var agent = navigator.userAgent.toLowerCase();
is_android = agent.indexOf('app_android') > 0;
is_ios = agent.indexOf('app_ios') > 0;
if(is_android)
this.val = "Android";
else if(is_ios)
this.val = "iOS";
else
this.val = "Web";
},
val: "Web"
}
};
AndroidBridge.java
@JavascriptInterface
public double get_latitude(){
GpsTracker gpsTracker = new GpsTracker(mainActivity);
return gpsTracker.getLatitude();
}
@JavascriptInterface
public double get_longitude(){
GpsTracker gpsTracker = new GpsTracker(mainActivity);
return gpsTracker.getLongitude();
}
ViewController.m
- (void)userContentController:(WKUserContentController*)userContentController
didReceiveScriptMessage:(WKScriptMessage*)message {
if([message.name isEqualToString:@"getCoordinate"]) {
[self getCurrentLocation];
if(latitude != nil && longitude != nil){
NSString *javaScript = [NSString stringWithFormat:@"window.nativeObj.coordinate.latitude = %@; window.nativeObj.coordinate.longitude = %@;", latitude, longitude];
[self.wkWebView evaluateJavaScript:javaScript completionHandler:nil];
}
}
}
함수 호출시
window.nativeObj.coordinate.getFromNative();
물론 객체를 사용하지 않거나, 객체를 사용하더라도 콜백 등을 구현해 이보다 간결하게 작성할 수 있겠지만..
네이티브 함수 호출이 그다지 많지 않을 것 같아서 이렇게만 해야겠다.
BIG