国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - IOS - iOS中使用JSPatch框架使Objective-C與JavaScript代碼交互

iOS中使用JSPatch框架使Objective-C與JavaScript代碼交互

2021-01-20 16:28琿少 IOS

有了JSPatch,我們便可以在iOS App開發中令JavaScript代碼調用原生的Objective-C屬性和方法等,下面就來詳細看一下如何在iOS中使用JSPatch框架使Objective-C與JavaScript代碼交互

JSPatch是GitHub上一個開源的框架,其可以通過Objective-C的run-time機制動態的使用JavaScript調用與替換項目中的Objective-C屬性與方法。其框架小巧,代碼簡潔,并且通過系統的JavaScriptCore框架與Objective-C進行交互,這使其在安全性和審核風險上都有很強的優勢。Git源碼地址:https://github.com/bang590/JSPatch。

一、從一個官方的小demo看起

通過cocoapods將JSPath集成進一個Xcode工程中,在AppDelegate類的中編寫如下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  //開始初始化引擎
  [JPEngine startEngine];
  //讀取js文件
  NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];
  NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
  //運行js文件
  [JPEngine evaluateScript:script];
  self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
  self.window.rootViewController = [[ViewController alloc]init];
  [self.window addSubview:[self genView]];
  [self.window makeKeyAndVisible];
  return YES;
}
 
- (UIView *)genView
{
  UIView * view= [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
  view.backgroundColor = [UIColor redColor];
  return view;
}

在工程中添加一個js文件,編寫如下:

  

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
require('UIView, UIColor, UILabel')
 //要替換函數的類
 defineClass('AppDelegate', {
     //替換函數
       //要替換函數的名稱
       genView: function() {
         var view = self.ORIGgenView();
         view.setBackgroundColor(UIColor.greenColor())
         var label = UILabel.alloc().initWithFrame(view.frame());
         label.setText("JSPatch");
         label.setTextAlignment(1);
         view.addSubview(label);
         return view;
     }
 });

運行工程,可以看到genView方法被替換成了js文件中的方法,原本紅色的視圖被修改成了綠色。

二、使用JavaScript代碼向Objective-C中修改或添加方法

JSPatch引擎中支持3中方式進行JavaScript代碼的調用,分別是使用JavaScript字符串進行代碼運行,讀取本地的JavaScript文件進行代碼運行和獲取網絡的JavaScript文件進行代碼運行。例如,如果想要通過JavaScript代碼在項目中彈出一個警告框,在Objective-C代碼中插入如下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
- (void)viewDidLoad {
  [super viewDidLoad];
  // ‘\'符用于進行換行
  [JPEngine evaluateScript:@"\
   var alertView = require('UIAlertView').alloc().init();\
   alertView.setTitle('Alert');\
   alertView.setMessage('AlertView from js'); \
   alertView.addButtonWithTitle('OK');\
   alertView.show(); \
   "];
}

開發者也可以動態在Objective-C類文件中添加方法,例如在ViewController類中編寫如下:

?
1
2
3
4
5
6
7
8
9
- (void)viewDidLoad {
  [super viewDidLoad];
  self.view.backgroundColor = [UIColor whiteColor];
  [JPEngine startEngine];
  NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];
  NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
  [JPEngine evaluateScript:script];
  [self performSelectorOnMainThread:@selector(creatView) withObject:nil waitUntilDone:nil];
}

JavaScript文件代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
require('UIView, UIColor, UILabel')
 defineClass('ViewController', {
     // replace the -genView method
       creatView: function() {
         var view = UIView.alloc().initWithFrame({x:20, y:20, width:100, height:100});
         view.setBackgroundColor(UIColor.greenColor());
         var label = UILabel.alloc().initWithFrame({x:0, y:0, width:100, height:100});
         label.setText("JSPatch");
         label.setTextAlignment(1);
         view.addSubview(label);
       self.view().addSubview(view)
     }
 });

除了上面的代碼,在ViewController.m文件中沒有編寫任何其他的方法,運行工程,可以看到程序并沒有崩潰,ViewController執行了creatView方法。

通過上面的示例,我們發現使用JSPatch可以做一些十分有趣的事。對于iOS應用來說,通過官方渠道AppStore進行應用程序的發布要通過人工審核,有時這個審核周期會非常長,如果在開發者在編寫代碼時留下了一些小漏洞,應用一旦上線,若要修改掉這個bug就十分艱難了。有了JSPatch,我們可以想象,如果可以定位到線上應用有問題的方法,使用JS文件來修改掉這個方法,這將是多么cool的一件事,事實上,JSPatch的主要用途也是可以實現線上應用極小問題的hotfix。

三、JavaScript與Objective-C交互的基礎方法

要使用JSPatch來進行Objective-C風格的方法編寫,需要遵守一些JavaScript與Objective-C交互的規則。

1.在JavaScript文件中使用Objective-C類

在編寫JavaScript代碼時如果需要用到Objective-C的類,必須先對這個類進行require引用,例如,如果需要使用UIView這個類,需要在使用前進行如下引用:

?
1
require('UIView')

同樣也可以一次對多個Objective-C類進行引用:

?
1
require('UIView, UIColor, UILabel')

還有一種更加簡便的寫法,直接在使用的時候對其進行引用:

?
1
require('UIView').alloc().init()

2.在JavaScript文件中進行Objective-C方法的調用

在進行Objective-C方法的調用時,分為兩種,一種是調用類方法,一種是調用類的對象方法。

調用類方法:通過類名打點的方式來調用類方法,格式類似如下,括號內為參數傳遞:

?
1
UIColor.redColor()

調用實例方法:通過對象打點的方式調用類的實例方法,格式如下,括號內為參數傳遞:

?
1
view.addSubview(label)

對于Objective-C中的多參數方法,轉化為JavaScript將參數分割的位置以_進行分割,參數全部放入后面的括號中,以逗號分割,示例如下:

view.setBackgroundColor(UIColor.colorWithRed_green_blue_alpha(0,0.5,0.5,1))
對于Objective-C類的屬性變量,在JavaScript中只能使用getter與setter方法來訪問,示例如下:

?
1
label.setText("JSPatch")

提示:如果原Objective-C的方法中已經包含了_符號,則在JavaScript中使用__代替。

3.在JavaScript中操作與修改Objective-C類

JSPatch的最大應用是在應用運行時動態的操作和修改類。

重寫或者添加類的方法:

在JavaScript中使用defineClass來定義和修改類中的方法,其編寫格式如下所示:

?
1
2
3
4
5
6
/*
classDeclaration:要添加或者重寫方法的類名 字符串 如果此類不存在 則會創建新的類
instanceMethods:要添加或者重寫的實例方法 {}
classMethods:要添加或者重寫的類方法 {}
*/
defineClass(classDeclaration, instanceMethods, classMethods)

示例如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
defineClass('ViewController', {
      // replace the -genView method
        newFunc: function() {
          //編寫實例方法
          self.view().setBackgroundColor(UIColor.redColor())
        }
  
      },{
 
        myLoad:function(){
          //編寫類方法
        }
 
      }
      )

如果在重寫了類中的方法后要調用原方法,需要使用ORIG前綴,示例如下:

?
1
2
3
4
5
6
7
8
9
defineClass('ViewController', {
      // replace the -genView method
        viewDidLoad: function() {
          //編寫實例方法
          self.ORIGviewDidLoad()
        }
  
      }
      )

對于Objective-C中super關鍵字調用的方法,在JavaScript中可以使用self.super()來調用,例如:

?
1
2
3
4
5
6
7
8
9
defineClass('ViewController', {
      // replace the -genView method
        viewDidLoad: function() {
          //編寫實例方法
          self.super().viewDidLoad()
        }
  
      }
      )

同樣JSPatch也可以為類添加臨時屬性,用于在方法間參數傳遞,使用set_Prop_forKey()來添加屬性,使用getProp()來獲取屬性,注意,JSPatch添加的屬性不能使用Objective-C的setter與getter方法訪問,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
defineClass('ViewController', {
      // replace the -genView method
        viewDidLoad: function() {
          //編寫實例方法
          self.super().viewDidLoad()
          self.setProp_forKey("JSPatch", "data")
        },
        touchesBegan_withEvent(id,touch){
          self.getProp("data")
          self.view().setBackgroundColor(UIColor.redColor())
        }
  
      }
      )

關于為類添加協議的遵守,和Objective-C中遵守協議的方式一致,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
defineClass("ViewController2: UIViewController <UIAlertViewDelegate>", {
      viewDidAppear: function(animated) {
      var alertView = require('UIAlertView')
      .alloc()
      .initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles(
                                        "Alert",
                                        "content",
                                        self,
                                        "OK",
                                        null
                                        )
      alertView.show()
      },
      alertView_clickedButtonAtIndex:function(alertView, buttonIndex) {
      console.log('clicked index ' + buttonIndex)
      }
      })

四、JavaScript與Objective-C交互的幾種常用類型

1.結構體

在Objective-C代碼中,我們經常會使用到結構體,JSPatch中原生支持的結構體有如下幾種:CGPoint,CGSize,CGRect,NSRange。并且這幾種結構體在進行界面操作時也會經常使用到。

對于CGRect類型,JavaScript使用如下代碼創建:

?
1
2
var view = require('UIView').alloc().init()
view.setFrame({x:100,y:100,width:100,height:100})

對于CGPoint類型,JavaScript使用如下代碼創建:

   

?
1
view.setCenter({x:200,y:200})

對于CGSize類型,JavaScript使用如下代碼創建:

?
1
2
var size = {width:200,height:200}
view.setFrame({x:100,y:100,width:size.width,height:size.height})

對于NSRange類型,JavaScript使用如下代碼創建:

?
1
var range = {location: 0, length: 1}

2.選擇器Selector

對于Objective-C中的方法選擇器Selector,在JavaScript中使用字符串的形式創建,例如:

?
1
self.performSelector_withObject("func:", 1)

3.關于空對象

在JavaScript中,null與undefined都對應于Objective-C中的nil,Objective-C中的NSNull空對象,在JavaScript中使用nsnull來代替。

4.在Objective-C與JavaScript中進行block的交互

在JavaScript與Objective-C進行block交互有兩種方式,一種是在JavaScript文件中調用Objective-C中的block,一種是將JavaScript文件中的函數塊作為block參數傳遞給Objective-C。

在JavaScript文件中使用Objective-C中的block十分簡單,因為JavaScript中沒有block的概念,Objective-C會被自動轉換為函數,示例如下:

Objective-C:

?
1
2
3
4
5
6
7
8
9
typedef void(^block)(NSString * str);
@interface ViewController ()
@end
@implementation ViewController
-(block)getBlock{
  block block = ^(NSString * str){NSLog(@"%@",str);};
  return block;
}
@end

JavaScript:

?
1
2
3
4
5
6
defineClass("ViewController", {
      viewDidAppear: function(animated) {
       var func = self.getBlock()
        func("123")
      }
      })

在JavaScript文件中將func作為參數block傳遞給Objective-C就復雜一些,需要使用block()方法進行包裝,例如:

Objective-C:

?
1
2
3
4
5
6
7
8
@interface ViewController ()
@end
@implementation ViewController
 
-(void)run:(void(^)(NSString * str))block{
  block(@"123");
}
@end

JavaScript:

?
1
2
3
4
5
6
defineClass("ViewController", {
      viewDidAppear: function(animated) {
      //run 方法中需要傳入一個block
      self.run(block("NSString*",function(str){console.log(str)}))
      }
      })

在使用block()方法對JavaScript中的Func進行包裝時,block(param1,param2)有兩個參數,第1個參數設置func中的參數類型,如果有多個參數,使用逗號分割;第2個參數為func函數體。

注意:在block()包裝的func中不可以使用self指針,如果需要使用self,需要在block外進行臨時變量的轉換,示例如下:

?
1
2
3
4
5
6
7
8
9
10
11
defineClass("ViewController", {
      viewDidAppear: function(animated) {
      //run 方法中需要傳入一個block
      var slf = self
      self.run(block("NSString*",
              function(str){
              console.log(str)
              slf.log(str)
              }))
      }
      })

在JavaScript中分別使用__weak()與__strong來聲明弱引用與強引用對象,例如:

?
1
2
var slf = __weak(self)
var stgSef = __strong(self)

5.關于GCD與枚舉

在JSPatch中,可以使用如下JavaScript代碼來調用GCD方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//阻塞當前線程一定時間
dispatch_after(1.0, function(){
})
//為主線程添加異步任務
dispatch_async_main(function(){
})
//為主線程添加同步任務
dispatch_sync_main(function(){
})
//向全局隊列中添加任務
dispatch_async_global_queue(function(){
})
JSPatch中不可以直接使用Objective-C中定義的枚舉,但是可以用其枚舉的真實值進行傳遞。例如:
 
//UIControlEventTouchUpInside的值是1<<6
btn.addTarget_action_forControlEvents(self, "handleBtn", 1<<6);

延伸 · 閱讀

精彩推薦
  • IOS詳解iOS中多個網絡請求的同步問題總結

    詳解iOS中多個網絡請求的同步問題總結

    這篇文章主要介紹了詳解iOS中多個網絡請求的同步問題總結,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...

    liang199111302021-03-15
  • IOSiOS開發技巧之狀態欄字體顏色的設置方法

    iOS開發技巧之狀態欄字體顏色的設置方法

    有時候我們需要根據不同的背景修改狀態欄字體的顏色,下面這篇文章主要給大家介紹了關于iOS開發技巧之狀態欄字體顏色的設置方法,文中通過示例代碼...

    夢想家-mxj8922021-05-10
  • IOSiOS實現控制屏幕常亮不變暗的方法示例

    iOS實現控制屏幕常亮不變暗的方法示例

    最近在工作中遇到了要將iOS屏幕保持常亮的需求,所以下面這篇文章主要給大家介紹了關于利用iOS如何實現控制屏幕常亮不變暗的方法,文中給出了詳細的...

    隨風13332021-04-02
  • IOSiOS中MD5加密算法的介紹和使用

    iOS中MD5加密算法的介紹和使用

    MD5加密是最常用的加密方法之一,是從一段字符串中通過相應特征生成一段32位的數字字母混合碼。對輸入信息生成唯一的128位散列值(32個字符)。這篇文...

    LYSNote5432021-02-04
  • IOSiOS中UILabel實現長按復制功能實例代碼

    iOS中UILabel實現長按復制功能實例代碼

    在iOS開發過程中,有時候會用到UILabel展示的內容,那么就設計到點擊UILabel復制它上面展示的內容的功能,也就是Label長按復制功能,下面這篇文章主要給大...

    devilx12792021-04-02
  • IOSiOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和Masonry簡單使用)

    iOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和

    這篇文章主要介紹了iOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和Masonry簡單使用)的相關資料,需要的朋友可以參考下...

    CodingFire13652021-02-26
  • IOSiOS開發之視圖切換

    iOS開發之視圖切換

    在iOS開發中視圖的切換是很頻繁的,獨立的視圖應用在實際開發過程中并不常見,除非你的應用足夠簡單。在iOS開發中常用的視圖切換有三種,今天我們將...

    執著丶執念5282021-01-16
  • IOSiOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果

    iOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果

    這篇文章主要介紹了iOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果的相關資料,需要的朋友可以參考下...

    jiangamh8882021-01-11
主站蜘蛛池模板: 国产精品美女久久久 | 成人在线一区二区三区 | 欧美一区二区黄色 | 黄色美女网站 | 欧美在线影院 | 黄片毛片| 国产伦精品一区二区三区四区视频 | 亚洲欧美激情精品一区二区 | 久久综合久久综合久久 | 91精品久久 | 亚洲免费观看视频 | 91超碰在线观看 | 最新国产视频 | 婷婷综合网 | 亚洲电影在线观看 | 亚洲福利影院 | 九一视频在线免费观看 | 波多一区二区 | 羞羞网站免费 | 久久天天躁狠狠躁夜夜躁2014 | 91亚洲精品乱码久久久久久蜜桃 | 五月激情综合网 | 1区2区视频 | 欧美日韩成人在线观看 | 日韩视频一区二区三区 | 中文字幕亚洲一区二区三区 | 国产精品2区 | 亚洲成人播放器 | 精品一区二区三区四区 | 久久久久久久久99精品 | 国产精品日韩高清伦字幕搜索 | 成年人在线免费观看视频网站 | 欧美一区二区最爽乱淫视频免费看 | 亚洲伦乱视频 | 精品久久一区 | 日韩精品影院 | 欧美一级片aaa | 欧美综合影院 | 国产一区二区av | 欧洲视频一区 | 久久久免费视频观看 |