bеplay9彩彩票信誉好不好不好问题解决了没有?现在那么多人怕它是怎么回事?

JSPatch基础用法总结
招聘信息:
1.打印console.log();2.Protocol//OC
可以在定义时让一个类实现某些&Protocol&接口,写法跟&OC&一样:
defineClass("JPViewController:&UIViewController",&{
这样做的作用是,当添加&Protocol&里定义的方法,而类里没有实现的方法时,参数类型不再全是&id,而是自动转为&Protocol&里定义的类型:
@protocol&UIAlertViewDelegate&
-&(void)alertView:(UIAlertView&*)alertView&clickedButtonAtIndex:(NSInteger)buttonI
defineClass("JPViewController:&UIViewController&",&{
&&viewDidAppear:&function(animated)&{
&&&&var&alertView&=&require('UIAlertView')
&&&&&&.alloc()
&&&&&&.initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles(
&&&&&&&&"Alert",
&&&&&&&&self.dataSource().objectAtIndex(indexPath.row()),&
&&&&&&&&self,&
&&&&&&&&"OK",&
&&&&&&&&null
&&&&&alertView.show()
&&alertView_clickedButtonAtIndex:&function(alertView,&buttonIndex)&{
&&&&console.log('clicked&index&'&+&buttonIndex)
})3.Masonry使用JSPatch如何写约束1)原来Masonry方法中"_"下划线的要变成两个"__"2)使用block块包装3)make中的方法都需要添加()//OC
UIView&*&view&=&[UIView&new];
&&&&view.backgroundColor&=&[UIColor&orangeColor];
&&&&[self.view&addSubview:view];
&&&&[view&mas_makeConstraints:^(MASConstraintMaker&*make)&{
&&&&&&&&make.top.equalTo(self.view).with.offset(15);
&&&&&&&&make.left.equalTo(self.view).with.offset(10);
&&&&&&&&make.right.equalTo(self.view.mas_width);
&&&&&&&&make.height.equalTo(@(50));
var&view&=&UIView.alloc().init();
&&&&&&&&&&&&&view.setBackgroundColor(UIColor.redColor());
&&&&&&&&&&&&&self.view().addSubview(view);
&&&&&&&&&&&&&console.log("222");
&&&&&&&&&&&&&view.mas__makeConstraints(block('MASConstraintMaker*',&function(make)&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&make.top().equalTo()(self.view()).with().offset()(15);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&make.left().equalTo()(self.view()).with().offset()(10);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&make.right().equalTo()(self.view().mas__right());&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&make.height().equalTo()((50));
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}));4.常用结构 同类方法,不能使用;结尾,需要使用逗号 或者什么都不写// JSdefineClass(“类名”,&{&&&&&&&&
&&//实例方法,不同方法之间使用逗号分隔
&&//类方法,不同方法之间使用逗号分隔
})5.require('UIColor,UIView,NSURL,NSURLRequest,UIFont,UILabel'); 导入头文件.6.在方法名前加 ORIG 即可调用未覆盖前的 OC 原方法://&OC
@implementation&JPTableViewController&
-&(void)viewDidLoad&{
defineClass("JPTableViewController",&{&&&&&&&&&&&&
viewDidLoad:&function()&{&&&&&&
self.ORIGviewDidLoad();&&&&&&
})7.动态新增 Property可以在 defineClass() 第二个参数为类新增 property,格式为字符串数组,使用时与 OC property 接口一致:defineClass("JPTableViewController",&['data',&'totalCount'],&{&&&&
init:&function()&{&&
self&=&self.super().init()&&&
self.setData(["a",&"b"])&&&&&//添加新的&Property&(id&data)&&&
self.setTotalCount(2)
return&self&&&
viewDidLoad:&function()&{&&&
var&data&=&self.data()&&&&&//获取&Property&值&&&
var&totalCount&=&self.totalCount()
})8.struct偏移量和转字符串var&contentOffSetY&=&scrollView.contentOffset().y;
var&string&=&NSString.stringWithFormat("%@",&contentOffSetY);
JSPatch原生支持&CGRect&/&CGPoint&/&CGSize&/&NSRange&这四个&struct&类型,用&JS&对象表示:
UIView&*view&=&[[UIView&alloc]&initWithFrame:CGRectMake(20,&20,&100,&100)];
[view&setCenter:CGPointMake(10,10)];
[view&sizeThatFits:CGSizeMake(100,&100)];
CGFloat&x&=&view.frame.origin.x;
NSRange&range&=&NSMakeRange(0,&1);
var&view&=&UIView.alloc().initWithFrame({x:20,&y:20,&width:100,&height:100})
view.setCenter({x:&10,&y:&10})
view.sizeThatFits({width:&100,&height:100})
var&x&=&view.frame().x&&&(orign也是一个结构体)
var&range&=&{location:&0,&length:&1}其他 Struct 类型的支持请参照 添加 struct 类型支持9.Selector &注意方法名左右是双引号 “”//Obj-C
[self&performSelector:@selector(viewWillAppear:)&withObject:@(YES)];
self.performSelector_withObject("viewWillAppear:",&1)10.nilJS 上的 null 和 undefined 都代表 OC 的 nil,如果要表示 NSNull, 用 nsnull 代替,如果要表示 NULL, 也用 null 代替://Obj-C
@implemention&JPTestObject
+&(BOOL)testNull(NSNull&*null)&{
&&&&return&[null&isKindOfClass:[NSNull&class]]
require('JPTestObject').testNull(nsnull)&//return&1
require('JPTestObject').testNull(null)&//return&0
在JS里面判断是否为空要判断false:
var&url&=&"";
var&rawData&=&NSData.dataWithContentsOfURL(NSURL.URLWithString(url));
if&(rawData&!=&null)&{}&//这样判断是错误的
应该如下判断:
if&(!rawData){}
在JSPatch.js源码里_formatOCToJS方法对undefined,null,isNil转换成了false。11. NSArray / NSString / NSDictionary如果使用self.dataArray() ==使用get方法 所以需要有括号 &如果直接使用数组 tempArray 不需要括号NSArray / NSString / NSDictionary 不会自动转成对应的JS类型,像普通 NSObject 一样使用它们://Obj-C
@implementation&JPObject&&
+&(NSArray&*)data
&&return&@[[NSMutableString&stringWithString:@"JS"]]&&
+&(NSMutableDictionary&*)dict&&
return&[[NSMutableDictionary&alloc]&init];&
require('JPObject')
var&ocStr&=&JPObject.data().objectAtIndex(0)&&&&
ocStr.appendString("Patch")&&
var&dict&=&JPObject.dict()
dict.setObject_forKey(ocStr,&'name')
console.log(dict.objectForKey('name'))&//output:&JSPatch
如果要把&NSArray&/&NSString&/&NSDictionary&转为对应的&JS&类型,使用&.toJS()&接口:
var&data&=&require('JPObject').data().toJS()&&
//data&instanceof&Array&===&true
data.push("Patch")
var&dict&=&JPObject.dict()
dict.setObject_forKey(data.join(''),&'name')
dict&=&dict.toJS()
console.log(dict['name'])&&&&//output:&JSPatch12. Block总结:1.JS调用OC方法中带有block的需要转换成block()格式.2.使用OC方法,传入参数为block,JS需要将block()结构JS 没有 block 类型的变量,OC 的 block 对象传到 JS 会变成 JS function,所有要从 JS 传 block 给 OC 都需要用 block() 接口包装。3.若使用 block 时出现 crash,最常见的原因是在 block 里使用了 self 变量,应该在 JS 声明另一个变量持有 self,详情见这里。block 传递当要把 JS 函数作为 block 参数给 OC时,需要先使用 block(paramTypes, function) 接口包装://&Obj-C&&
@implementation&JPObject&&
+&(void)request:(void(^)(NSString&*content,&BOOL&success))callback
&&callback(@"I'm&content",&YES);&
require('JPObject').request(block("NSString&*,&BOOL",&function(ctn,&succ)&{&
&&if&(succ)&log(ctn)&&//output:&I'm&content&
}))这里 block 里的参数类型用字符串表示,写上这个 block 各个参数的类型,用逗号分隔。NSObject 对象如 NSString , NSArray 等可以用 id 表示,但 block 对象要用 NSBlock* 表示。从 OC 返回给 JS 的 block 会自动转为 JS function,直接调用即可://&Obj-C&&
@implementation&JPObject&
typedef&void&(^JSBlock)(NSDictionary&*dict);&
+&(JSBlock)genBlock&
&&NSString&*ctn&=&@"JSPatch";&
&&JSBlock&block&=&^(NSDictionary&*dict)&{&
&&&&&&&NSLog(@"I'm&%@,&version:&%@",&ctn,&dict[@"v"])&
&&return&&
+&(void)execBlock:(JSBlock)blk&
var&blk&=&require('JPObject').genBlock();
blk({v:&"0.0.1"});&&//output:&I'm&JSPatch,&version:&0.0.1若要把这个从 OC 传过来的 block 再传回给 OC,同样需要再用 block() 包装,因为这里 blk 已经是一个普通的 JS function,跟我们上面定义的 JS function 没有区别://&JS
var&blk&=&require('JPObject').genBlock();&
blk({v:&"0.0.1"});&&//output:&I'm&JSPatch,&version:&0.0.1&
require('JPObject').execBlock(block("id",&blk));总结:JS 没有 block 类型的变量,OC 的 block 对象传到 JS 会变成 JS function,所有要从 JS 传 block 给 OC 都需要用 block() 接口包装。block 里使用 self 变量在 block 里无法使用 self 变量,需要在进入 block 之前使用临时变量保存它:defineClass("JPViewController",&{&
&&viewDidLoad:&function()&{&
&&&&var&slf&=&&
&&&&require("JPTestObject").callBlock(block(function(){&
&&&&&&//`self`&is&not&available&here,&use&`slf`&instead.&
&&&&&&slf.doSomething();&
&&&&&&});&
}限制从 JS 传 block 到 OC,有两个限制:A. block 参数个数最多支持6个。(若需要支持更多,可以修改源码)B. block 参数类型不能是 double / NSBlock / struct 类型。另外不支持 JS 封装的 block 传到 OC 再传回 JS 去调用(原因见 issue #155):-&(void)callBlock:(void(^)(NSString&*str))block&{&
defineClass('JPTestObject',&{&
&&&&run:&function()&{
&&&&&&&&self.callBlock(block('NSString*',&function(str)&{
&&&&&&&&&&&&console.log(str);&
&&&&&&&&}));&
&&&&callBlock:&function(blk)&{&
&&&&&&&&//blk&这个&block&是上面的&run&函数里&JS&传到&OC&再传过来的,无法调用。&
&&&&&&&&blk("test&block");&&&&
});常用例子://OC&
secondVC.buttonBlock&=&^(NSString&*&string)&
&&&&&&NSLog(@"原声打印:&%@",string);&
&var&func&=&function(string)&
&console.log(string);&
&&//然后setblock&
&&block包装(参数,block块)&
&&secondVC.setButtonBlock(block('NSString*',func));13.weak / strong可以在 JS 通过 __weak() 声明一个 weak 变量,主要用于避免循环引用。例如我们在 OC 里为了避免 block 导致的循环引用,经常这样写:-&(void)test&{&
&&&&_weak&id&weakSelf&=&
&&&&[self&setCompleteBlock:^(){
&&&&&&&&[weakSelf&blabla];
}在 JS 对应的可以这样写:var&weakSelf&=&__weak(self)&
self.setCompleteBlock(block(function(){
&&&&weakSelf.blabla();&
}))若要在使用 weakSelf 时把它变成 strong 变量,可以用 __strong() 接口:var&weakSelf&=&__weak(self)&&
self.setCompleteBlock(block(function(){&&
&&&&var&strongSelf&=&__strong(weakSelf)&
&&&&strongSelf.blabla();&&
}))14. GCD使用 dispatch_after() dispatch_async_main() dispatch_sync_main() dispatch_async_global_queue() 接口调用GCD方法://&Obj-C&&
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,&(int64_t)(1.0&*&NSEC_PER_SEC)),&dispatch_get_main_queue(),&^{&&
&&//&do&something
dispatch_async(dispatch_get_main_queue(),&^{&&
&&//&do&something&&
dispatch_after(1.0,&function(){&&
&&//&do&something&&
dispatch_async_main(function(){&&
&&//&do&something&&
dispatch_sync_main(function(){&&
&&//&do&something&&
dispatch_async_global_queue(function(){&&
&&//&do&something&&
})15. 常量、枚举、宏、全局变量常量/枚举Objective-C 里的常量/枚举不能直接在 JS 上使用,可以直接在 JS 上用具体值代替://OC&
[btn&addTarget:self&action:@selector(handleBtn)&&&
forControlEvents:UIControlEventTouchUpInside];
//UIControlEventTouchUpInside的值是1<<6&&
btn.addTarget_action_forControlEvents(self,&"handleBtn",&1<<6);&&
或者在&JS&上重新定义同名的全局变量:&&
var&UIControlEventTouchUpInside&&=&1&<<&6;&&
btn.addTarget_action_forControlEvents(self,&"handleBtn",&UIControlEventTouchUpInside);&&
有些常量字符串,需要在&OC&用&NSLog&打出看看它的值是什么:&&
[[NSAttributedString&alloc].initWithString:@"str"&attributes:@{NSForegroundColorAttributeName:&[UIColor&redColor]];&&
上面代码中&NSForegroundColorAttributeName&是一个静态字符串常量,源码里看不出它的值,可以先用&NSLog&打出它的值再直接写在&JS&上:&&
NSLog(@"%@",&NSForegroundColorAttributeName)&//output&&#39;NSColor&#39;
NSAttributedString.alloc().initWithString_attributes("无效啊",&{&#39;NSColor&#39;:&UIColor.redColor()});&&
NSFontAttributeName&==&NSFont
NSParagraphStyleAttributeName&==&NSParagraphStyle&&
NSForegroundColorAttributeName&==&NSColor&&
var&paragraphStyle&=&NSMutableParagraphStyle.alloc().init();&&
&&&&&&paragraphStyle.setLineSpacing(2);&//&字体的行间距
&&&&&&paragraphStyle.setAlignment(3);
&&&&&&paragraphStyle.setLineBreakMode(0);
&&&&&&var&attributes&=&{
&&&&&&NSFont:&UIFont.systemFontOfSize(20),
&&&&&&NSParagraphStyle:&paragraphStyle,
&&&&&&NSColor:&UIColor.redColor()
&&&&&&};&&
&&&&&&var&attributesString&=&NSAttributed&&String.alloc().initWithString_attributes("我就是测试",&attributes);&&
&&&&&&self.contentLabel().setAttributedText(attributesString);宏获取宏值Objective-C 里的宏同样不能直接在 JS 上使用。若定义的宏是一个值,可以在 JS 定义同样的全局变量代替,若定义的宏是程序,可以在JS展开宏:#define&TABBAR_HEIGHT&40
#define&SCREEN_WIDTH&[[UIScreen&mainScreen]&bounds].size.height
[view&setWidth:SCREEN_WIDTH&height:TABBAR_HEIGHT];
view.setWidth_height(UIScreen.mainScreen().bounds().height,&40);若宏的值是某些在底层才能获取到的值,例如 CGFLOAT_MIN,可以通过在某个类或实例方法里将它返回,或者用添加扩展的方式提供支持:@implementation&JPMacroSupport
+&(void)main:(JSContext&*)context&&
&&context[@"CGFLOAT_MIN"]&=&^CGFloat()&{&&
&&&&return&CGFLOAT_MIN;&&
require(&#39;JPEngine&#39;).addExtensions([&#39;JPMacroSupport&#39;])&&
var&floatMin&=&CGFLOAT_MIN();修改宏值JSPatch 不支持修改宏的值,若要修改,需要替换所有使用到这个宏的方法。例如:#define&VIEW_HEIGHT&40
@implementation&JPMethodDemo
+&(void)func&&
&&UIView&*view&=&[[UIView&alloc]&initWithFrame:CGRectMake(0,&0,&100,&VIEW_HEIGHT)];&&
var&VIEW_HEIGHT_NEW&=&20;
defineClass(&#39;JPMethodDemo&#39;,&{
&&func:&function()&{
&&&&&&var&view&=&UIView.alloc().initWithFrame({x:0,&y:0,&width:100,&height:VIEW_HEIGHT_NEW});&&
&&&&&&...&&
});全局变量在类里定义的 static 全局变量无法在 JS 上获取到,若要在 JS 拿到这个变量,需要在 OC 有类方法或实例方法把它返回:static&NSString&*
@implementation&JPTestObject
+&(NSString&*)name&{
var&name&=&JPTestObject.name()&&//拿到全局变量值16.stringWithFormatJSPatch 支持调用 stringWithFormat,不过所有参数类型都需改为 %@://OC
[NSString&stringWithFormat:@"name:%@,&age:%d",&@"alex",&12];
NSString.stringWithFormat("name:%@,&age:%@",&"alex",&12);虽然支持 stringWithFormat,但还是建议使用 JS 语法拼接字符串:var&ret&=&"name:"&+&"alex"&+&"&age:("&+&12&+&")";17.NSNumber 相关问题NSNumber 与上述四个类型不一样,所有数值类型以及 NSNumber 对象到 JS 后都会变成数值,不能再调用这个数值的任何方法://OC
@implementation&JPTestObject
+&(NSNumber&*)returnNSNumber&{
&&&&return&@(42);
+&(int)returnInt
&&return&42;
var&numFromOC&=&JPTestObject.returnNumber()
var&intFromOC&=&JPTestObject.returnInt()
var&jsNum&=&42
//以上三个变量是相等的:
console.log(numFromOC&==&intFromOC&==&jsNum)&//true
//不能调用&NSNumber&方法:
numFromOC.isEqualToNumber(42);&&//crash
//所有数值操作都应该在&JS&语法下操作:
parseInt(numFromOC);
var&all&=&numFromOC&+&intFromOC&+&jsN18.for...in首先从 OC 返回的 NSArray / NSDictionary 对象是不能直接用 for...in 遍历的,需要调用 .toJS() 后才能进行遍历,详情见上文。然后在遍历数组时,JavaScript 的 for...in 语法定义与 Objective-C 不同://OC
NSArray&*arr&=&@[@"name",&@"age"];
for&(var&o&in&arr)&{
&&NSLog(@"%@",&o);&//输出&name&age
var&arr&=&["name",&"age"];
for&(var&o&in&arr)&{
&&console.log(o);&//输出&0,&1,表示遍历数组的序号
&&console.log(arr[o]);&//输出&name&age,这样才表示数组的值
}18.内存释放问题如果一个 OC 对象被 JS 引用,或者在 JS 创建这个对象,这个 OC 对象在退出作用域后不会马上释放,而是会等到 JS 垃圾回收时才释放,这会导致一些 OC 对象延迟释放:defineClass(&#39;JPTestObject&#39;,&{
&&testObj:&function()&{
&&&&var&view&=&UIView.alloc().init();
&&&&//函数执行完退出作用域,或者手动把这个变量置为null,这个&OC&对象都不会立即释放
&&&&//在&JS&没有变量持有这些对象后,JS&引擎会在垃圾回收时才释放
&&&&view&=&
});没有被 JS 引用过的 OC 对象不受影响。更多讨论见 #6919.dealloc 问题可以用 JSPatch 为类添加 dealloc 方法,但无法覆盖原 OC 上的 dealloc 方法,在执行完 JS 的 dealloc 后会自动执行 OC 上的 dealloc 方法,因为若不执行 OC 的 dealloc 方法,对象无法正常释放,会产生内存泄漏:@implementation&JPViewController
-&(void)dealloc&{
&&&&NSLog(@"dealloc&from&OC");
defineClass(&#39;JPViewController&#39;,&{
&&&&dealloc:&function()&{
&&&&&&&&console.log(&#39;dealloc&from&JS&#39;);
dealloc&from&JS
dealloc&from&OC
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量5730点击量5026点击量3505点击量2571点击量2433点击量2178点击量2074点击量1878点击量1814
&2016 Chukong Technologies,Inc.
京公网安备89JSPatch 实现原理详解_iOS开发by唐巧_传送门
你是真实用户吗(Are you a robot)?
我们怀疑你不是真实用户,已对你的访问做了限制。如果您是真实用户,非常抱歉我们的误判对您造成的影响,您可以通过QQ()或电子邮件()反馈给我们,并在邮件和QQ请求信息里注明您的IP地址:220.177.198.53,我们会尽快恢复您的正常访问权限。另外,如果您不是在访问的当前页面,我们建议您移步
或者 在浏览器中输入以下地址:http://chuansong.me/n/1428932 访问,您所访问的网站是从抓取的数据,请直接访问,会有更好的体验和更及时的更新。We suspect you are a robot.We are really sorry if you are not,and you can email us () with your current IP address: 220.177.198.53 to get full access to .If you are not accessing
for the current page,you'd better visit
for better performance,as the current website you are accessing is just spam.
觉得不错,分享给更多人看到
iOS开发by唐巧 微信二维码
分享这篇文章
6月5日 16:25
iOS开发by唐巧 最新头条文章
iOS开发by唐巧 热门头条文章iOS开发JSPatch在线热修复技术简介 - 简书
iOS开发JSPatch在线热修复技术简介
JSPatch 是一个 iOS 动态更新框架,只需在项目中引入极小的引擎,就可以使用 JavaScript 调用任何 Objective-C 原生接口,获得脚本语言的优势:为项目动态添加模块,或替换项目原生代码动态修复 bug。
JSPatch 的基本原理就是:JS 传递字符串给 OC,OC 通过 Runtime 接口调用和替换 OC 方法。
JSPatch在App中工作流程:每次启动时在appDelegate中向服务器请求js文件,若服务器上的js文件版本和app本地中的版本不同,证明有新的补丁要执行。下载最新的js文件到本地并进行热修复。
JS如何替换OC代码:利用OC的消息转发机制。(这部分不理解的,出门左转有runtime简介)1、替换原有selector的IMP实现为一个空的实现,这样当objc_class接收到消息之后,就会进行消息转发。2、将替换的JS方法构造一个JSselector及其IMP实现,添加到当前class中3、然后改写每个替换方法类的forwadInvocation的实现进行拦截。如果拦截到的Invocation的selector转换成JSselector能够响应,说明正是要被替换的目标方法,从Invocation中取出参数后调用JSselector的IMP实现。
简单使用demo:1、前往
平台注册应用获得appkey及sdk2、导入JSPatch.framework,libz以及JavaScriptCore.framework3、若只进行本地测试,在AppDelegate.m中调用 [JSPatch testScriptInBundle]; 若进行服务器测试,调用[JSPatch startWithAppKey:@""];
//检查补丁更新
[JSPatch sync];4、新建main.js文件,编写补丁的内容。以下代码演示在线让ViewController的view的backgroundColor变为红色的js代码。定义了一个testJsPatch方法,并在方法里设置颜色。然后在viewDidLoad方法里调用。
require('UIColor');
defineClass('ViewController', {
viewDidLoad: function() {
self.super().viewDidLoad();
self.testJsPatch();
testJsPatch: function() {
self.view().setBackgroundColor(UIColor.redColor());
不想深入学习语法只想使用的同学可以到 下载语言转换器,只要写好oc的代码,复制过去就能自动生成对应的js代码。需要注意的是,oc代码中不能包含NSLog。
使用中的注意点:1、传输安全:JS 脚本可以调用任意 OC 方法,权限非常大,若被中间人攻击替换代码,会造成较大的危害。解决方法:使用RSA 校验。
2、执行安全:下发的 JS 脚本灵活度大,相当于一次小型更新,若未进行充分测试,可能会出现 crash 等情况对 APP 稳定性造成影响。解决方法:1、不用一次性下发到所有用户,逐步下发。
2、进行回退。JSPatch库, 一个Apple官方支持的实现在线更新iOS应用的库
来源:博客园
简介 项目主页: /bang590/JSPatch 示例下载: /ios122/ios122 JSPatch 可以让你用 JavaScript 书写原生 iOS APP。只需在项目引入极小的引擎,就可以使用 JavaScript 调用任何 Objective-C 的原生接口,获得脚本语言的优势:为项目动态添加模块,或替换项目原生代码动态修复 bug。 优势 在项目中引入JSPatch,就可以在发现bug时下发JS脚本替换原生方法,可以做到无需更新整个APP即时修复bug! JSPatch用iOS内置的 JavaScriptCore.framework作为引擎;JSPatch也符合苹果的规则。苹果不允许动态下发可执行代码,但通过苹果 JavaScriptCore.framework 或 WebKit 执行的代码除外,JS 正是通过 JavaScriptCore.framework 执行的。 JSPatch非常小巧 实例预览 @implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[JPEngine startEngine];
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];
NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
[JPEngine evaluateScript:script];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[self.window addSubview:[self genView]];
[self.window makeKeyAndVisible];
return YES;}- (UIView *)genView{
return [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];}@end // demo.js require ( 'UIView, UIColor, UILabel' ) defineClass ( 'AppDelegate' , { // 替换这个 -genView 方法 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) ; } } ) ; 安装 通过Cocopods安装 pod 'JSPatch' # 在线更新应用. 手动导入 下载 /bang590/JSPatch 并解压 复制JSPatch文件夹到你的工程 使用 objective-C: 导入头文件#import "JPEngine.h" 导入本地JS(demo.js)见文首github示例demo(可选,实际项目中,根据自己实际需要进行.) 调用 [JPEngine startEngine] 加载引擎 通过 [JPEngine evaluateScript:@""] 接口执行 JavaScript。 [JPEngine startEngine];// 直接执行js[JPEngine evaluateScript:@"\ var alertView = require('UIAlertView').alloc().init();\ alertView.setTitle('Alert');\ alertView.setMessage('AlertView from js'); \ alertView.addButtonWithTitle('OK');\ alertView.show(); \"];// 从网络拉回js脚本执行[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://cnbang.net/test.js"]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSString *script = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[JPEngine evaluateScript:script];}];// 执行本地js文件NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"js"];NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];[JPEngine evaluateScript:script]; // 另一个例子// 加载引擎[JPEngine startEngine];
本地JS,动态更新技术就是通过服务器获取JS更新这个JSNSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];[JPEngine evaluateScript:script] JavaScript: 基础使用方式 // 调用require引入要使用的OC类 require ( 'UIView, UIColor, UISlider, NSIndexPath' ) // 调用类方法 var redColor = UIColor . redColor () ; // 调用实例方法 var view = UIView . alloc (). init () ; view . setNeedsLayout () ; // set proerty view . setBackgroundColor (redColor) ; // get property var bgColor = view . backgroundColor () ; // 多参数方法名用'_'隔开: // OC:NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1]; var indexPath = NSIndexPath . indexPathForRow_inSection ( 0 , 1 ) ; // 方法名包含下划线'_',js用双下划线表示 // OC: [JPObject _privateMethod]; JPObject . __privateMethod () // 如果要把 `NSArray` / `NSString` / `NSDictionary` 转为对应的 JS 类型,使用 `.toJS()` 接口. var arr = require ( 'NSMutableArray' ). alloc (). init () arr . addObject ( "JS" )jsArr = arr . toJS () console . log ( jsArr . push ( "Patch" ). join ( '' )) //output: JSPatch // 在JS用字典的方式表示 CGRect / CGSize / CGPoint / NSRange var view = UIView . alloc (). initWithFrame ( { x : 20 , y : 20 , width : 100 , height : 100 } ) ; var x = view . bounds . // block 从 JavaScript 传入 Objective-C 时,需要写上每个参数的类型。 // OC Method: + (void)request:(void(^)(NSString *content, BOOL success))callback require ( 'JPObject' ). request ( block ( "NSString *, BOOL" , function (ctn , succ) { if (succ) log (ctn) } )) ; // GCD dispatch_after ( function ( 1.0 , function () { // do something } )) dispatch_async_main ( function () { // do something } ) 详细文档请参考wiki页面: 基础用法 定义类/替换方法 用 defineClass() 定义 Objective-C 的类,对类和实例方法进行动态替换。 // OC@implementation JPTableViewController...- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *content = self.dataSource[[indexPath row]];
//may cause out of bound
JPViewController *ctrl = [[JPViewController alloc] initWithContent:content];
[self.navigationController pushViewController:ctrl];}- (NSArray *)dataSource{
return @[@"JSPatch", @"is"];}- (void)customMethod{
NSLog(@"callCustom method")}@end // JSdefineClass("JPTableViewController", {
// instance method definitions
tableView_didSelectRowAtIndexPath: function(tableView, indexPath) {
var row = indexPath.row()
if (self.dataSource().count() > row) {
//fix the out of bound bug here
var content = self.dataSource().objectAtIndex(row);
var ctrl = JPViewController.alloc().initWithContent(content);
self.navigationController().pushViewController(ctrl);
dataSource: function() {
// get the original method by adding prefix 'ORIG'
var data = self.ORIGdataSource().toJS();
return data.push('Good!');
}}, {}) 详细文档请参考wiki页面: defineClass的用法 扩展 一些自定义的struct类型、C函数调用以及其他功能可以通过扩展实现,调用 +addExtensions: 可以加载扩展接口: @implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[JPEngine startEngine];
//添加扩展
[JPEngine addExtensions:@[@"JPInclude", @"JPCGTransform"]];
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];
NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
[JPEngine evaluateScript:script];} include ( 'test.js' ) //`include()`方法在扩展 JPInclude.m 里提供 var view = require ( 'UIView' ). alloc (). init () //struct CGAffineTransform 类型在 JPCGTransform.m 里提供支持 view . setTransform ( { a : 1 , b : 0 , c : 0 , d : 1 , tx : 0 , ty : 100 } ) 扩展可以在JS动态加载,更推荐这种加载方式,在需要用到时才加载: require ( 'JPEngine' ). addExtensions ([ 'JPInclude' , 'JPCGTransform' ]) // `include()` and `CGAffineTransform` is avaliable now. 可以通过新增扩展为自己项目里的 struct 类型以及C函数添加支持,详情请见wiki页面: 添加新扩展 安全性 JSPatch非常强大,因而最好将通过服务器获取JS的链接进行加密,本地JS也最好加密处理 注: 文章由我们 iOS122 的小伙伴 **@偌一茗* * 整理,喜欢就一起参与: iOS122 任务池
免责声明:本站部分内容、图片、文字、视频等来自于互联网,仅供大家学习与交流。相关内容如涉嫌侵犯您的知识产权或其他合法权益,请向本站发送有效通知,我们会及时处理。反馈邮箱&&&&。
学生服务号
在线咨询,奖学金返现,名师点评,等你来互动}

我要回帖

更多关于 88赌城信誉好不好 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信