Web和Native的交互,也就是iOS object-C與javascript之間的交互;核心代碼是
[webView stringByEvaluatingJavascriptFromString:@"xxxxxxxxxx"];
這里主要用到的就是iOS WebKit加載網絡頁面,功能有獲取用戶位置信息,拍照,判斷當前手機網絡連接類型的功能(拍照和獲取當前用戶地理位置需要真機環境下)所以需要導入以下幾個框架:
這里需要注意的是iOS8以后獲取位置地理信息需要在info.plist文件中手動添加:
NSLocationWhenInUseUsageDescriptionNSLocationAlwaysUsageDescription
設置他們的鍵值為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.VEVb.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 : NSObjecttypedef 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謝謝
新聞熱點
疑難解答