1. 程式人生 > >JS與OC互調,JS開啟系統相機,JS獲取iOS系統圖片,iOS中JS調OC

JS與OC互調,JS開啟系統相機,JS獲取iOS系統圖片,iOS中JS調OC

廢話不多說,直接進入正題

1.首先在在viewController中實現JavaScript代理

我直接把.m檔案中的內容全部貼上了,看註釋,大家懂得

  1. #import "ViewController.h"
  2. #import <JavaScriptCore/JavaScriptCore.h>// 匯入JavaScriptCore 系統框架檔案
  3. #import "SaveImage_Util.h"// 這是儲存圖片的類
  4. /** 
  5.  *  實現js代理,js呼叫ios的入口就在這裡 
  6.  */
  7. @protocol JSDelegate <JSExport>  
  8. - (void)getImage:(id
    )parameter;// 這個方法就是window.document.iosDelegate.getImage(JSON.stringify(parameter)); 中的 getImage()方法
  9. @end
  10. @interface ViewController ()<JSDelegate,UIWebViewDelegate,UINavigationControllerDelegate,UIImagePickerControllerDelegate>//匯入代理  JSDelegate UIWebViewDelegate,UINavigationControllerDelegate,UIImagePickerControllerDelegate 這兩個代理是開啟系統相機的代理
  11. /** 
  12.  *  宣告 兩個屬性, 
  13.  */
  14. @property(strongnonatomicJSContext *jsContext;  
  15. @property(retainnonatomicUIWebView *myWebView;  
  16. @end
  17. @implementation ViewController  
  18. {  
  19.     int indextNumb;// 交替圖片名字
  20.     UIImage *getImage;//獲取的圖片
  21. }  
  22. - (void)viewDidLoad {  
  23.     [super viewDidLoad];  
  24.     [self gotoWebView];  
  25. }  
  26. - (void
    )gotoWebView  
  27. {  
  28.     if (!self.myWebView)  
  29.     {  
  30.         //初始化 WebView
  31.         self.myWebView = [[UIWebView alloc] initWithFrame:  
  32.                         CGRectMake(00self.view.bounds.size.widthself.view.bounds.size.height-100)];  
  33.         self.myWebView.backgroundColor = [UIColor colorWithRed:1.000 green:1.000 blue:0.400 alpha:1.000];  
  34.         // 代理
  35.         self.myWebView.delegate = self;  
  36.         NSURL *path = [[NSBundle mainBundle] URLForResource:@"testJS" withExtension:@"html"];  
  37.         [self.myWebView loadRequest:[NSURLRequest requestWithURL:path]];  
  38.         [self.view addSubview:self.myWebView];  
  39.     }  
  40. }  
  41. #pragma mark UIWebViewDelegate 
  42. // 載入完成開始監聽js的方法
  43. - (void)webViewDidFinishLoad:(UIWebView *)webView  
  44. {  
  45.     self.jsContext = [self.myWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];  
  46.     self.jsContext[@"iosDelegate"] = self;//掛上代理  iosDelegate是window.document.iosDelegate.getImage(JSON.stringify(parameter)); 中的 iosDelegate
  47.     self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception){  
  48.         context.exception = exception;  
  49.         NSLog(@"獲取 self.jsContext 異常資訊:%@",exception);  
  50.     };  
  51. }  
  52. - (void)getImage:(id)parameter  
  53. {  
  54.     // 把 parameter json字串解析成字典
  55.     NSString *jsonStr = [NSString stringWithFormat:@"%@", parameter];  
  56.     NSDictionary *jsParameDic = [NSJSONSerialization JSONObjectWithData:[jsonStr dataUsingEncoding:NSUTF8StringEncoding ] options:NSJSONReadingAllowFragments error:nil];  
  57.     NSLog(@"js傳來的json字典: %@", jsParameDic);  
  58.     for (NSString *key in jsParameDic.allKeys)  
  59.     {  
  60.         NSLog(@"jsParameDic[%@]:%@", key, jsParameDic[key]);  
  61.     }  
  62.     [self beginOpenPhoto];  
  63. }  
  64. - (void)beginOpenPhoto  
  65. {  
  66.     // 主佇列 非同步開啟相機
  67.     dispatch_async(dispatch_get_main_queue(), ^{  
  68.         [self takePhoto];  
  69.     });  
  70. }  
  71. #pragma mark 取消選擇照片代理方法
  72. - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker  
  73. {  
  74.     [picker dismissViewControllerAnimated:YES completion:nil];  
  75. }  
  76. #pragma mark      //開啟本地照片
  77. - (void) localPhoto  
  78. {  
  79.     UIImagePickerController *imagePicker = [[UIImagePickerController alloc]init];  
  80.     imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;  
  81.     imagePicker.delegate = self;  
  82.     [self presentViewController:imagePicker animated:YES completion:nil];  
  83. }  
  84. #pragma mark      //開啟相機拍照
  85. - (void) takePhoto  
  86. {  
  87.     UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;  
  88.     if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])  
  89.     {  
  90.         UIImagePickerController *picker = [[UIImagePickerController alloc]init];  
  91.         picker.delegate = self;  
  92.         picker.allowsEditing = YES;  
  93.         picker.sourceType = sourceType;  
  94.         picker.modalTransitionStyle = UIModalTransitionStyleCoverVertical;  
  95.         [self presentViewController:picker animated:YES completion:nil];  
  96.     }  
  97.     else
  98.     {  
  99.         NSLog(@"模擬器中不能開啟相機");  
  100.         [self localPhoto];  
  101.     }  
  102. }  
  103. //  選擇一張照片後進入這裡
  104. - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info  
  105. {  
  106.     NSString *type = [info objectForKey:UIImagePickerControllerMediaType];  
  107.     //  當前選擇的型別是照片
  108.     if ([type isEqualToString:@"public.image"])  
  109.     {  
  110.         // 獲取照片
  111.         getImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];  
  112.         NSLog(@"===Decoded image size: %@", NSStringFromCGSize(getImage.size));  
  113.         // obtainImage 壓縮圖片 返回原尺寸
  114.         indextNumb = indextNumb == 1?2:1;  
  115.         NSString *nameStr = [NSString stringWithFormat:@"Varify%d.jpg",indextNumb];  
  116.         [SaveImage_Util saveImage:getImage ImageName:nameStr back:^(NSString *imagePath) {  
  117.             dispatch_async(dispatch_get_main_queue(), ^{  
  118.                 NSLog(@"圖片路徑:%@",imagePath);  
  119.                 /** 
  120.                  *  這裡是IOS 調 js 其中 setImageWithPath 就是js中的方法 setImageWithPath(),引數是字典 
  121.                  */
  122.                 JSValue *jsValue = self.jsContext[@"setImageWithPath"];  
  123.                 [jsValue callWithArguments:@[@{@"imagePath":imagePath,@"iosContent":@"獲取圖片成功,把系統獲取的圖片路徑傳給js 讓html顯示"}]];  
  124.             });  
  125.         }];  
  126.         [picker dismissViewControllerAnimated:YES completion:nil];  
  127.     }  
  128. }  
  129. - (void)didReceiveMemoryWarning {  
  130.     [super didReceiveMemoryWarning];  
  131.     // Dispose of any resources that can be recreated.
  132. }  
  133. @end

2.儲存圖片的類SaveImage_Util.h和.m檔案中的程式碼,該類繼承NSObject

  1. //  SaveImage_Util.h
  2. //  JS和iOS互動
  3. //
  4. //  Created by user on 16/7/28.
  5. //  Copyright © 2016年 user. All rights reserved.
  6. //
  7. #import <Foundation/Foundation.h>
  8. #import <UIKit/UIKit.h>
  9. @interface SaveImage_Util : NSObject  
  10. #pragma mark  儲存圖片到document
  11. + (BOOL)saveImage:(UIImage *)saveImage ImageName:(NSString *)imageName back:(void(^)(NSString *imagePath))back;  
  12. @end

  1. //  SaveImage_Util.m
  2. //  JS和iOS互動
  3. //
  4. //  Created by user on 16/7/28.
  5. //  Copyright © 2016年 user. All rights reserved.
  6. //
  7. #import "SaveImage_Util.h"
  8. @implementation SaveImage_Util  
  9. #pragma mark  儲存圖片到document
  10. + (BOOL)saveImage:(UIImage *)saveImage ImageName:(NSString *)imageName back:(void(^)(NSString *imagePath))back  
  11. {  
  12.     NSString *path = [SaveImage_Util getImageDocumentFolderPath];  
  13.     NSData *imageData = UIImagePNGRepresentation(saveImage);  
  14.     NSString *documentsDirectory = [NSString stringWithFormat:@"%@/", path];  
  15.     // Now we get the full path to the file
  16.     NSString *imageFile = [documentsDirectory stringByAppendingPathComponent:imageName];  
  17.     // and then we write it out
  18.     NSFileManager *fileManager = [NSFileManager defaultManager];  
  19.     //如果檔案路徑存在的話
  20.     BOOL bRet = [fileManager fileExistsAtPath:imageFile];  
  21.     if (bRet)  
  22.     {  
  23.         //        NSLog(@"檔案已存在");
  24.         if ([fileManager removeItemAtPath:imageFile error:nil])  
  25.         {  
  26.             //            NSLog(@"刪除檔案成功");
  27.             if ([imageData writeToFile:imageFile atomically:YES])  
  28.             {  
  29.                 //                NSLog(@"儲存檔案成功");
  30.                 back(imageFile);  
  31.             }  
  32.         }  
  33.         else
  34.         {  
  35.         }  
  36.     }  
  37.     else
  38.     {  
  39.         if (![imageData writeToFile:imageFile atomically:NO])  
  40.         {  
  41.             [fileManager createDirectoryAtPath:documentsDirectory withIntermediateDirectories:YES attributes:nil error:nil];  
  42.             if ([imageData writeToFile:imageFile atomically:YES])  
  43.             {  
  44.                 back(imageFile);  
  45.             }  
  46.         }  
  47.         else
  48.         {  
  49.             returnYES;  
  50.         }  
  51.     }  
  52.     returnNO;  
  53. }  
  54. #pragma mark  從文件目錄下獲取Documents路徑
  55. + (NSString *)getImageDocumentFolderPath  
  56. {  
  57.     NSString *patchDocument = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];  
  58.     return [NSString stringWithFormat:@"%@/Images", patchDocument];  
  59. }  
  60. @end



3. 接下來就是HTML檔案中的標籤及JS程式碼,這裡的JS就不單獨用一個類實現了,就在testJS.html中實現。
  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <metacharset="UTF-8">
  5.         <title></title>
  6.     </head>
  7.     <body>
  8.         <div>
  9.             <h3>JS與iOS互動</h3>
  10.             <h4>JS頁面獲取iOS系統圖片</h5>
  11.         </div>
  12.         <div>
  13.             <inputtype = "button"style="width: 50%;height: 5%;"id="Button"value="開啟相機獲取圖片"onclick="getIOSImage()"></button>
  14.         </div><dir/>
  15.         <div>
  16.             <imgsrc="testImage.png"id="changeImage"style="width: 30%; height: 30%;" onclick="getIOSImage()"><!--src="圖片的相對路徑" 如果把html檔案匯入工程中,圖片路徑和OC一樣只寫圖片名字和字尾就可以,(記得要先把圖片新增到工程) 圖片也可以實現按鈕的方法getIOSImage -->
  17.         </div>
  18.         <spanid="iosParame"style="width: 200px; height: 50%; color:orangered; font-size:15px"value="等待獲取ios引數">
  19.             </div>
  20.         <script>
  21.             var getIOSImage = function(){  
  22.                 var parameter = {'title':'JS調OC','describe':'這裡就是JS傳給OC的引數'};  
  23.                 // 在下面這裡實現js 呼叫系統原生api  
  24.     window.iosDelegate.getImage(JSON.stringify(parameter));// 實現資料的 json 格式字串  
  25.             }  
  26.         // 這裡是 iOS呼叫js的方法  
  27.         function setImageWithPath(arguments){  
  28.             document.getElementById('changeImage').src = arguments['imagePath'];  
  29.             document.getElementById('iosParame').innerHTML = arguments['iosContent'];  
  30.         }  
  31.         </script>
  32.     </body>
  33. </html>
注意:在js獲取的object物件的解析和取值的方式有兩種,一種類似OC的方法(上面HTML中寫的方法: arguments['iosContent']),另一種是用eval()方法,如 [javascript] view plain copy
  1. document.getElementById('iosParame').innerHTML = eval("arguments."+'iosContent');  
下面是我除錯醜醜的效果圖: