iOS Native-Web交互學習心得

来源:http://www.cnblogs.com/shouce/archive/2016/04/29/5445038.html
-Advertisement-
Play Games

Web和Native的交互,也就是iOS object-C與Javascript之間的交互;核心代碼是 [webView stringByEvaluatingJavaScriptFromString:@"xxxxxxxxxx"]; 這裡主要用到的就是iOS WebKit載入網路頁面,功能有獲取用戶位 ...


Web和Native的交互,也就是iOS object-CJavascript之間的交互;核心代碼是

[webView stringByEvaluatingJavaScriptFromString:@"xxxxxxxxxx"];

 

這裡主要用到的就是iOS WebKit載入網路頁面,功能有獲取用戶位置信息,拍照,判斷當前手機網路連接類型的功能(拍照和獲取當前用戶地理位置需要真機環境下)所以需要導入以下幾個框架:

 這裡需要註意的是iOS8以後獲取位置地理信息需要在info.plist文件中手動添加:

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謝謝


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • App Store: 天的故事 一個寫故事、分享故事、閱讀故事的應用。 五彩繽紛的首頁。 故事有開端、中段、結尾,一天有上午、下午、晚上,每一天都是個完整的故事,也是個多彩的故事。 好故事要能一句話概括,天的故事只要330字,配上豐富的色彩來表現感受和心情,天的故事簡潔美觀,有趣易讀。 在這裡,你可 ...
  • 跳到健康設置 上網找了一下 你會發現很難找到。代碼如下 不信你試試 。 NSURL *url = [NSURL URLWithString:@"prefs:root=Privacy&path=HEALTH"]; if ([[UIApplication sharedApplication] canOp ...
  • 今天在查看蘋果介面文檔時,突然對於介面的聲明知識點比較感興趣,再網路找到下麵這個比較不錯的文章,記錄一下並分享; 如你所知,已廢棄(Deprecated)的API指的是那些已經過時的並且在將來某個時間最終會被移除掉的方法或類。通常,蘋果在引入一個更優秀的API後就會把原來的API給廢棄掉。因為,新引 ...
  • 繼續前兩篇,接著本第三篇《學習Coding-iOS開源項目日誌(三)》講解Coding-iOS開源項目。 前 言:作為初級程式員,想要提高自己的水平,其中一個有效的學習方法就是學習別人好的項目。本篇開始會陸續更新本人對github上開源的一個很不 錯的項目的一點點學習積累。也就是,探究著別人寫的源碼 ...
  • ➠更多技術乾貨請戳:聽雲博客 Charles是一款抓包修改工具,相比起TcpDump,charles具有界面簡單直觀,易於上手,數據請求控制容易,修改簡單,抓取數據的開始暫停方便等等優勢!前面介紹瞭如何使用TcpDump抓包,下麵給大家介紹一下Charles的使用。 Charles抓包 Charle ...
  • 作為一種輕量級的數據交換格式,json正在逐步取代xml,成為網路數據的通用格式。 有的json代碼格式比較混亂,可以使用此“http://www.bejson.com/”網站來進行JSON格式化校驗(點擊打開鏈接)。此網站不僅可以檢測Json代碼中的錯誤,而且可以以視圖形式顯示json中的數據內容 ...
  • 1、原來是將EditView放到了popupwindow,發現EditView原有的複製、粘貼、全選、選擇功能失效了,所以便用DialogFragment代替了popupWindow 直接上代碼 ①、先看佈局文件 ②、看自定義diaglogFragment的代碼 3、如何使用 效果圖 ...
  • 1.Socket 幾個常用的名詞 IPC—>Inter Process Communication,進程間通信 socket —> 套接字 TCP—>Transmission Control Protocol傳輸控制協議, 什麼是Socket Socket:又稱作是套接字,網路上的兩個程式通過一個雙 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...