Web和Native的交互,也就是iOS object-C与Javascript之间的交互;核心代码是
[webView stringByEvaluatingJavaScriptFromString:@"xxxxxxxxxx"];
这里主要用到的就是iOS WebKit加载网络页面,功能有获取用户位置信息,拍照,判断当前手机网络连接类型的功能(拍照和获取当前用户地理位置需要真机环境下)所以需要导入以下几个框架:
这里需要注意的是iOS8以后获取位置地理信息需要在info.plist文件中手动添加:
class="prettyprint">NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
设置他们的键值为YES;
那么现在我们的准备工作就做好了;
首先加载本地的Html文件:这里因为需要调用系统相机所以添加代理UIWebViewDelegate,UINavigationControllerDelegate, UIImagePickerControllerDelegate
@interface ViewController ()<UIWebViewDelegate,UINavigationControllerDelegate, UIImagePickerControllerDelegate>
{
NSString *callback;
}
@property (nonatomic,strong) UIWebView *webView;
@property (nonatomic,strong) MapViewController *map;
@end
@implementation ViewController
- (void)viewDidLoad { [super viewDidLoad]; _webView = [[UIWebView alloc]initWithFrame:self.view.bounds]; [self.view addSubview:_webView]; _webView.delegate = self; NSString *filePath = [[NSBundle mainBundle] pathForResource:@"api" ofType:@"html"]; NSString *fileContent = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; [_webView loadHTMLString:fileContent baseURL:nil]; }
现在开始上干货了:WebViewDelegate代理方法
//js调用iOS - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString *requestString = [[request URL] absoluteString]; //jS协议头 NSString *protocol = @"js-call://"; //请求的字符串符合协议头 if ([requestString hasPrefix:protocol]) { //从协议头后的位置截取字符串到最后 NSString *requestContent = [requestString substringFromIndex:[protocol length]]; //将/分隔的字符串转换成数组 NSArray *vals = [requestContent componentsSeparatedByString:@"/"]; if ([[vals objectAtIndex:0] isEqualToString:@"camera"]) { callback = [vals objectAtIndex:1]; [self doAction:UIImagePickerControllerSourceTypeCamera]; } else if([[vals objectAtIndex:0] isEqualToString:@"photolibrary"]) { callback = [vals objectAtIndex:1]; [self doAction:UIImagePickerControllerSourceTypePhotoLibrary]; } else if([[vals objectAtIndex:0] isEqualToString:@"album"]) { callback = [vals objectAtIndex:1]; [self doAction:UIImagePickerControllerSourceTypeSavedPhotosAlbum]; } else if([[vals objectAtIndex:0] isEqualToString:@"location"]) { callback = [vals objectAtIndex:1]; [self sendlocationInformation]; } else if([[vals objectAtIndex:0] isEqualToString:@"netType"]) { callback = [vals objectAtIndex:1]; [self sendNetWorkType]; } else { [webView stringByEvaluatingJavaScriptFromString:@"alert('未定义/lwme.cnblogs.com');"]; } return NO; } return YES; }
点击加载的Web页面的按钮,native端响应事件:
- (void)doAction:(UIImagePickerControllerSourceType)sourceType { UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; imagePicker.delegate = self; if ([UIImagePickerController isSourceTypeAvailable:sourceType]) { imagePicker.sourceType = sourceType; } else { UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"照片获取失败" message:@"没有可用的照片来源" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; [av show]; return; } if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:imagePicker]; [popover presentPopoverFromRect:CGRectMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 3, 10, 10) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } else { [self presentViewController:imagePicker animated:YES completion:nil]; } }
拍照,获取相册的代理方法:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { if ([[info objectForKey:UIImagePickerControllerMediaType] isEqualToString:@"public.image"]) { UIImage *originalImage = [info objectForKey:UIImagePickerControllerOriginalImage]; UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"正在处理图片..." message:@"\n\n" delegate:self cancelButtonTitle:nil otherButtonTitles:nil, nil]; UIActivityIndicatorView *loading = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; loading.center = CGPointMake(139.5, 75.5); [av addSubview:loading]; [loading startAnimating]; [av show]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ NSString *base64 = [UIImageJPEGRepresentation(originalImage,0.5) base64EncodedStringWithOptions:0]; [self performSelectorOnMainThread:@selector(doCallback:) withObject:base64 waitUntilDone:NO]; [av dismissWithClickedButtonIndex:0 animated:YES]; }); } [picker dismissViewControllerAnimated:YES completion:nil]; } - (void)doCallback:(NSString *)data { [_webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"%@('%@');", callback, data]]; }
Web页面的HTML代码信息:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>微信JS-SDK Demo</title> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0"> <link rel="stylesheet" href="css/style_demo.css"> <script> function openLocation(){ window.location.href="js-call://location/locationCallback"; } function chooseImage(){ window.location.href="js-call://photolibrary/photolibraryCallback"; } function goCamera(){ window.location.href="js-call://camera/cameraCallback"; } function getNetType(){ window.location.href="js-call://netType/netTypeCallback"; } function openAlbum(){ window.location.href="js-call://album/albumCallback"; } function cameraCallback(imageData) { var img = createImageWithBase64(imageData); document.getElementById("camera_image_div").appendChild(img); } function photolibraryCallback(imageData) { var img = createImageWithBase64(imageData); document.getElementById("choose_image_div").appendChild(img); } function albumCallback(imageData) { var img = createImageWithBase64(imageData); document.getElementById("open_image_div").appendChild(img); } function createImageWithBase64(imageData) { var img = new Image(); img.src = "data:image/jpeg;base64," + imageData; img.style.width = "200px"; img.style.height = "200px"; return img; } </script> </head> <body ontouchstart=""> <div class="wxapi_container"> <div class="lbox_close wxapi_form"> <h3 id="menu-image">图像接口</h3> <span class="desc">地理位置</span> <button class="btn btn_primary" id="openLocation" onclick="openLocation()">地理位置</button> <span id="spLoc" class="desc"></span> <span class="desc">选择图片</span> <button class="btn btn_primary" id="chooseImage" onclick="chooseImage()">选择图片</button> <div id="choose_image_div"></div> <span class="desc">拍照</span> <button class="btn btn_primary" id="takePic" onclick="goCamera()">拍照</button> <div id="camera_image_div"></div> <span class="desc">网络连接类型</span> <button class="btn btn_primary" id="netType" onclick="getNetType()">网络连接类型</button> <span id="spNet" class="desc"></span> <span class="desc">相册</span> <button class="btn btn_primary" id="openAlbum" onclick="openAlbum()">打开相册</button> <div id="open_image_div"></div> <div id="hidpicdiv" style="display: none;"> <img id="hidpic" src="" width="200" height="200"/> </div> </div> </div> </body>
获取当前用户位置信息和判断当前手机的连接网络类型:
- (void)sendNetWorkType { if ([NetWorkType getNetworkTypeFromStatusBar]==0) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"网络连接类型" message:@"当前无网络连接" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; } if ([NetWorkType getNetworkTypeFromStatusBar]==1) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"网络连接类型" message:@"当前2G连接" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; } if ([NetWorkType getNetworkTypeFromStatusBar]==2) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"网络连接类型" message:@"当前为3G连接" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; } if ([NetWorkType getNetworkTypeFromStatusBar]==3) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"网络连接类型" message:@"当前为4G连接" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; } if ([NetWorkType getNetworkTypeFromStatusBar]==5) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"网络连接类型" message:@"当前为WIFI连接" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; } } - (void)sendlocationInformation { _map = [[MapViewController alloc]init]; _map.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:_map animated:YES completion:nil]; }
获取当前用户的位置信息:
头文件导入:
#import <MapKit/MapKit.h> #import <CoreLocation/CoreLocation.h>
加载地图:
@interface MapViewController ()<MKMapViewDelegate,CLLocationManagerDelegate> { NSString *locationStr; } @property (nonatomic,strong) MKMapView *mapView; @property (nonatomic,strong) CLLocationManager *locationManager; @end @implementation MapViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. _mapView = [[MKMapView alloc]initWithFrame:self.view.frame]; [self.view addSubview:_mapView]; UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; backButton.frame = CGRectMake((self.view.bounds.size.width)/2-40, 20, 80, 30); [backButton setTitle:@"返回" forState:UIControlStateNormal]; [backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; backButton.backgroundColor = [UIColor cyanColor]; backButton.titleLabel.textAlignment = NSTextAlignmentCenter; [backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; [_mapView addSubview:backButton]; // 1.跟踪用户位置(显示用户的具体位置) self.mapView.userTrackingMode = MKUserTrackingModeFollow; // 2.设置地图类型 self.mapView.mapType = MKMapTypeStandard; // 3.设置代理 self.mapView.delegate = self; _locationManager = [[CLLocationManager alloc] init]; _locationManager.delegate = self; //设置定位精度 _locationManager.desiredAccuracy=kCLLocationAccuracyBest; //定位频率,每隔多少米定位一次 CLLocationDistance distance=1.0;//1米定位一次 _locationManager.distanceFilter=distance; _locationManager.desiredAccuracy=kCLLocationAccuracyBest; if([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { [_locationManager requestWhenInUseAuthorization]; } [_locationManager startUpdatingLocation]; } #pragma mark - MKMapViewDelegate /** * 当用户的位置更新,就会调用 * * @param userLocation 表示地图上蓝色那颗大头针的数据 */ - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { CLLocationCoordinate2D center = userLocation.location.coordinate; // 设置地图的显示范围, 让其显示到当前指定的位置 MKCoordinateSpan span = MKCoordinateSpanMake(0, 0);//这个显示大小精度自己调整 MKCoordinateRegion region = MKCoordinateRegionMake(center, span); [mapView setRegion:region animated:YES]; } //可以通过模拟器设置一个虚拟位置,否则在模拟器中无法调用此方法 -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ CLLocation *location=[locations firstObject];//取出第一个位置 CLLocationCoordinate2D coordinate=location.coordinate;//位置坐标 locationStr = [NSString stringWithFormat:@"经度:%f,纬度:%f,海拔:%f,航向:%f,行走速度:%f",coordinate.longitude,coordinate.latitude,location.altitude,location.course,location.speed]; //如果不需要实时定位,使用完即使关闭定位服务 [_locationManager stopUpdatingLocation]; } - (void)back { [self dismissViewControllerAnimated:YES completion:nil]; }
判断当前手机网络连接的类型:
这里我写了一个类方法,因为我们判断当前用户使用的网络连接方式可以从状态栏信息中获取:
在.h中:
@interface NetWorkType : NSObject typedef enum { NETWORK_TYPE_NONE= 0, NETWORK_TYPE_2G= 1, NETWORK_TYPE_3G= 2, NETWORK_TYPE_4G= 3, NETWORK_TYPE_5G= 4,// 5G目前为猜测结果 NETWORK_TYPE_WIFI= 5, }NETWORK_TYPE; +(NETWORK_TYPE)getNetworkTypeFromStatusBar; @end
在.m:
#import "NetWorkType.h" #import "AppDelegate.h" @implementation NetWorkType +(NETWORK_TYPE)getNetworkTypeFromStatusBar { UIApplication *app = [UIApplication sharedApplication]; NSArray *subviews = [[[app valueForKey:@"statusBar"] valueForKey:@"foregroundView"] subviews]; NSNumber *dataNetworkItemView = nil; for (id subview in subviews) { if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) { dataNetworkItemView = subview; break; } } NETWORK_TYPE nettype = NETWORK_TYPE_NONE; NSNumber * num = [dataNetworkItemView valueForKey:@"dataNetworkType"]; nettype = [num intValue]; return nettype; } @end
下面就是我写的关于这个demo运行的效果图片:
以上就是自己写的iOS Native-Web交互方面的心得,转载请说明出处;O(∩_∩)O谢谢