如何用苹果账号登陆twitter-威尼斯人2299

网络节点

该楼层疑似违规已被系统折叠?隐藏此楼查看此楼

求大神!!!

单点登录的cas在服务器上运行时,点击记住密码会报500错误(不点记住密码能正常登录)。

把子站调到本机后能记住密码也能正常运行。

服务器环境:tomcat7 jdk7

服务器报错日志:

七月 04, 2018 9:49:23 上午 org.apache.catalina.core.standardwrappervalve invoke

严重: servlet.service() for servlet [cas] in context with path [/cas] threw exception [request processing failed; nested exception is java.lang.runtimeexception: org.springframework.webflow.execution.actionexecutionexception: exception thrown executing [annotatedaction@46c02ae6 targetaction = [evaluateaction@72408653 expression = utryauthenticationviaformaction.submitandfireevent(flowrequestcontext, flowscope.credential, messagecontext), resultexpression = [null]], attributes = map[[empty]]] in state 'realsubmit' of flow 'login' -- action execution attributes were 'map[[empty]]'] with root cause

java.lang.error: unresolved compilation problem:

the method sethttponly(boolean) is undefined for the type cookie

at utry.cas.web.util.cookieutil.setcookie(cookieutil.java:87)

at utry.cas.web.flow.utryauthenticationviaformaction.rememberme(utryauthenticationviaformaction.java:113)

at utry.cas.web.flow.utryauthenticationviaformaction.submitandfireevent(utryauthenticationviaformaction.java:76)

at sun.reflect.generatedmethodaccessor102.invoke(unknown source)

at sun.reflect.delegatingmethodaccessorimpl.invoke(delegatingmethodaccessorimpl.java:43)

at java.lang.reflect.method.invoke(method.java:606)

at org.springframework.expression.spel.support.reflectivemethodexecutor.execute(reflectivemethodexecutor.java:113)

at org.springframework.expression.spel.ast.methodreference.getvalueinternal(methodreference.java:102)

at org.springframework.expression.spel.ast.methodreference.access$000(methodreference.java:49)

at org.springframework.expression.spel.ast.methodreference$methodvalueref.getvalue(methodreference.java:347)

at org.springframework.expression.spel.ast.compoundexpression.getvalueinternal(compoundexpression.java:88)

at org.springframework.expression.spel.ast.spelnodeimpl.gettypedvalue(spelnodeimpl.java:131)

at org.springframework.expression.spel.standard.spelexpression.getvalue(spelexpression.java:299)

at org.springframework.binding.expression.spel.springelexpression.getvalue(springelexpression.java:84)

at org.springframework.webflow.action.evaluateaction.doexecute(evaluateaction.java:75)

at org.springframework.webflow.action.abstractaction.execute(abstractaction.java:188)

at org.springframework.webflow.execution.annotatedaction.execute(annotatedaction.java:145)

爬取(食品招商网)app spzs ? 里面的代理信息,web上无法显示,只能下载app

爬取流程:

1.电脑和手机连接同一个wifi,设置fiddler端口8888,设置手机wifi为手动连接,ip地址同电脑,端口同fiddler

2.手机浏览器访问 ip:端口,下载fiddler证书(我刚刚连接的时候可能是操作太快,网络无法访问,下次记得重启一下fiddler或者等待一会)

3.fiddler抓包成功后,手机打开app

?

?4.发现这种app几乎没有反爬,直接把headers和data复制过来,在python里面构造一下

爬取完成

?

这是比较简单的app爬虫,困难点的需要xpose和just trust me ,再难一点则要js逆向来获取某些参数(以后随缘更新,如果有业务需求再来拓展)

这篇文章主要介绍了苹果手机怎么用蓝牙传照片到安卓手机,具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获,下面让小编带着大家一起了解一下。

2019独角兽企业重金招聘python工程师标准>>>?

让你的ios应用程序支持运行javascript脚本:javascriptcore框架详解

? ? 说到javascript脚本,ios开发者都会想到一个名叫javascriptcore的框架。这个框架的确十分强大,其中封装了一套javascript运行环境以及native与js数据类型之间的转换桥梁快码论文。本篇博客主要讨论如何使用此框架来在ios应用中运行javascript脚本。

一、javascriptcore框架结构

? ? 在学习一个框架时,首先应该先了解整个框架的结构,拿ios开发来举例,对于一个陌生的框架,第一步需要先搞清楚这里面都包含哪些类,个各类之间是怎样的关系,这个框架和其他的框架间有无联系以及怎样产生的联系。将些问题搞清楚,有了大体上的认识后,我们再来学习其中的每个类即其他细节的应用将非常容易。我们先来看一张javascriptcore框架的结构图:

这张图是我手工画的,不是那么美观并且没有文字的解释,但是我觉得它能非常直观的表达javascriptcore中包含的类之间的关系。下面我来向你解释这张图究竟表达了什么意思,首先原生的ios应用是支持多线程执行任务的,我们知道javascript是单线程,但这并不代表我们不能在native中异步执行不同的javascript代码。

1.jsvirtualmachine——javascript的虚拟机

????javascriptcore中提供了一个名为jsvirtualmachine的类,顾名思义,这个类可以理解为一个js虚拟机。在native中,只要你愿意,你可以创建任意多个jsvirtualmachine对象,各个jsviretualmachine对象间是相互独立的,他们之间不能共享数据也不能传递数据,如果你把他们放在不同的native线程,他们就可以并行的执行无关的js任务。

2.jscontext——javascript运行环境

? ? jscontext上下文对象可以理解为是js的运行环境,同一个jsvirtualmachine对象可以关联多个jscontext对象,并且在webview中每次刷新操作后,此webview的js运行环境都是不同的jscontext对象。其作用就是用来执行js代码,在native和js间进行数据的传递。

3.jsvalue——javascript值对象

? ? javascript和objective-c虽然都是面向对象语言,但其实现机制完全不同,oc是基于类的,js是基于原型的,并且他们的数据类型间也存在很大的差异。因此若要在native和js间无障碍的进行数据的传递,就需要一个中间对象做桥接,这个对象就是jsvalue。

4.jsexport

? ? jsexport是一个协议,native中遵守此解析的类可以将方法和属性转换为js的接口供js调用。

5.一些用于c语言的结构

? ? 你一定注意到了,上图的右下角还有一块被虚线包围的区域,其中的"类"都是c语言风格,javascriptcore框架是支持在objective-c、swift和c三种语言中使用的。

二、在native中运行javascript脚本代码

? ? 我们先来编写一个最简单的例子,使用oc代码来执行一段js脚本。首先新建一个文件,将其后缀设置为.js,我这里将它命令为main.js,在其中编写如下代码:

(function(){

console.log("hello native");

})();

上面是一个自执行的函数,其中打印了“hello native”字符串。在native中编写如下代码:

- (void)viewdidload {

[super viewdidload];

nsstring * path = [[nsbundle mainbundle] pathforresource:@"main" oftype:@"js"];

nsdata * jsdata = [[nsdata alloc]initwithcontentsoffile:path];

nsstring * jscode = [[nsstring alloc]initwithdata:jsdata encoding:nsutf8stringencoding];

self.jscontext = [[jscontext alloc]init];

[self.jscontext evaluatescript:jscode];

}

需要注意,其实这里我将创建的jscontext对象作为了当前视图控制器的属性,这样做的目的仅仅是为了方便调试,不过不对此context对象进行引用,当viewdidload函数执行完成后,js运行环境也将被销毁,我们就无法在safari中直观的看到js代码的执行结果了。

? ? 运行工程,记得要打开safari浏览器的自动显示jscontent检查器,如下图:

当ios模拟器跑起来后,safari会自动弹出开发者工具,在控制台里面可以看到来自javascript的真挚问候:

刚才我们只是简单了通过原生调用了一段js代码,但是如果native在调js方法时无法传参那也太low了,我们可以直接将要传递的参数格式化到字符串中,修改main.js文件如下:

function put(name){

console.log("hello " name);

};

put(%@);

再封装一个oc方法如下:

-(void)runjs_hello:(nsstring *)name{

nsstring * path = [[nsbundle mainbundle] pathforresource:@"main" oftype:@"js"];

nsdata * jsdata = [[nsdata alloc]initwithcontentsoffile:path];

nsstring * jscode = [[nsstring alloc]initwithdata:jsdata encoding:nsutf8stringencoding];

nsstring * finistring = [nsstring stringwithformat:jscode,name];

[self.jscontext evaluatescript:finistring];

}

在viewdidload中进行调用,如下:

- (void)viewdidload {

[super viewdidload];

self.jscontext = [[jscontext alloc]init];

[self runjs_hello:@"'阿凡达'"];

}

运行再看safari控制台的结果,编程了hello 阿凡达~:

其实evaluatescript函数执行后会将js代码的执行结果进行返回,是jsvalue类型的对象,后面会再介绍。

三、在javascript中调用native方法

? ? 有来无往非君子,同样也可以在原生中编写方法让js来调用,示例如下:

- (void)viewdidload {

[super viewdidload];

void(^block)() = ^(){

nslog(@"hello javascript");

};

self.jscontext = [[jscontext alloc]init];

[self.jscontext setobject:block forkeyedsub:@"oc_hello"];

}

上面setobject:forkeyedsub:方法用来向jscontext环境的全局对象中添加属性,这里添加了一个函数属性,取名为oc_hello。这里javascriptcore会自动帮我们把一些数据类型进行转换,会将oc的函数转换为js的函数,运行工程,在safari的控制台中调用oc_hello函数,可以看到在xcode控制台输出了对javascript的真挚问候,如下:

同样,如果声明的block是带参数的,js在调用此oc方法时也需要传入参数,如果block有返回值,则在js中也能获取到返回值,例如:

bool (^block)(nsstring *) = ^(nsstring *name){

nslog(@"%@", [nsstring stringwithformat:@"hello %@",name]);

return yes;

};

self.jscontext = [[jscontext alloc]init];

[self.jscontext setobject:block forkeyedsub:@"oc_hello"];

四、深入jscontext类

? ? 看到这,你已经学会最基础的oc与js互相问好(交互)。下面我们再来深入看下jscontext中的属性和方法。

? ? 创建jscontext对象有如下两种方式:

//创建一个新的js运行环境

- (instancetype)init;

//创建一个新的js运行环境 并关联到某个虚拟机对象上

- (instancetype)initwithvirtualmachine:(jsvirtualmachine *)virtualmachine;

? ? 执行js代码有如下两个方法:

//执行js代码 结果将封装成jsvalue对象返回

- (jsvalue *)evaluatescript:(nsstring *);

//作用同上

- (jsvalue *)evaluatescript:(nsstring *) withsourceurl:(nsurl *)sourceurl ns_available(10_10, 8_0);

? ? 下面的属性和方法可以获取到js运行环境中的一些信息:

//当前的js运行环境 当js调用oc方法时,在oc方法中可以用此方法获取到js运行环境

(jscontext *)currentcontext;

//获取当前执行的js函数,当js调用oc方法时,在oc方法中可以用此方法获取到执行的函数

(jsvalue *)currentcallee;

//获取当前执行的js函数中的this指向的对象

(jsvalue *)currentthis;

//获取当前执行函数的参数列表,当js调用oc方法时,在oc方法中可以用此方法获取到执行的函数的参数列表

(nsarray *)currentarguments;

//获取当前js运行环境的全局对象

@property (readonly, strong) jsvalue *globalobject;

//当运行的javascript代码抛出了未捕获的异常时,这个属性会被赋值为抛出的异常

@property (strong) jsvalue *exception;

//设置为一个异常捕获的block,如果异常被此block捕获,exception属性就不再被赋值了

@property (copy) void(^exceptionhandler)(jscontext *context, jsvalue *exception);

//当前运行环境所关联的虚拟机

@property (readonly, strong) jsvirtualmachine *virtualmachine;

//当前运行环境名称

@property (copy) nsstring *name;

//获取当前js运行环境全局对象上的某个属性

- (jsvalue *)objectforkeyedsub:(id)key;

//设置当前js运行环境全局对象上的属性

- (void)setobject:(id)object forkeyedsub:(nsobject *)key;

//将c语言环境的js运行环境转换为oc环境的js运行环境

(jscontext *)contextwithjsglobalcontextref:(jsglobalcontextref)jsglobalcontextref;

//c语言环境的js运行上下文

@property (readonly) jsglobalcontextref jsglobalcontextref;

五、深入jsvalue类

? ? jsvalue是javascript与objective-c之间的数据桥梁。在objective-c中调用js脚本或者js调用oc方法都可以使用jsvalue来传输数据。其中属性和方法示例如下:

//所对应的js运行环境

@property (readonly, strong) jscontext *context;

//在指定的js运行环境中创建一个jsvalue对象

(jsvalue *)valuewithobject:(id)value incontext:(jscontext *)context;

//创建布尔值

(jsvalue *)valuewithbool:(bool)value incontext:(jscontext *)context;

//创建浮点值

(jsvalue *)valuewithdouble:(double)value incontext:(jscontext *)context;

//创建32位整型值

(jsvalue *)valuewithint32:(int32_t)value incontext:(jscontext *)context;

//创建32位无符号整形值

(jsvalue *)valuewithuint32:(uint32_t)value incontext:(jscontext *)context;

//创建空的js对象

(jsvalue *)valuewithnewobjectincontext:(jscontext *)context;

//创建空的js数组

(jsvalue *)valuewithnewarrayincontext:(jscontext *)context;

//创建js正则对象

(jsvalue *)valuewithnewregularexpressionfrompattern:(nsstring *)pattern flags:(nsstring *)flags incontext:(jscontext *)context;

//创建js错误信息

(jsvalue *)valuewithnewerrorfrommessage:(nsstring *)message incontext:(jscontext *)context;

//创建js null值

(jsvalue *)valuewithnullincontext:(jscontext *)context;

//创建js undefined值

(jsvalue *)valuewithundefinedincontext:(jscontext *)context;

javascript中的数据类型和objective-c的数据类型还是有着很大的差异,其中对应关系如下:

objective-c?javascriptnilundefinednsnullnullnsstringstringnsnumbernumber booleannsdictionary ??objectnsarrayarraynsdatedate? ?blockfunctionidobjectclassobject

下面这些方法可以将jsvalue值转换为objective-c中的数据类型:

//将jsvalue转换为oc对象

- (id)toobject;

//将jsvalue转换成特定oc类的对象

- (id)toobjectofclass:(class)expectedclass;

//将jsvalue转换成布尔值

- (bool)tobool;

//将jsvalue转换成浮点值

- (double)todouble;

//将jsvalue转换成32位整型值

- (int32_t)toint32;

//将jsvalue转换成32位无符号整型值

- (uint32_t)touint32;

//将jsvalue转换成nsnumber值

- (nsnumber *)tonumber;

//将jsvalue转换成nsstring值

- (nsstring *)tostring;

//将jsvalue转换成nsdate值

- (nsdate *)todate;

//将jsvalue转换成nsarray值

- (nsarray *)toarray;

//将jsvalue转换成nsdictionary值

- (nsdictionary *)todictionary;

//获取jsvalue对象中某个属性的值

- (jsvalue *)valueforproperty:(nsstring *)property;

//设置jsvalue对象中某个属性的值

- (void)setvalue:(id)value forproperty:(nsstring *)property;

//删除jsvalue对象中的某个属性

- (bool)deleteproperty:(nsstring *)property;

//判断jsvalue对象中是否包含某个属性

- (bool)hasproperty:(nsstring *)property;

//定义jsvalue中的某个属性 这个方法和javascript中object构造函数的defineproperty方法一致

/*

第2个参数设置此属性的描述信息 可以设置的键值如下:

nsstring * const jspropertydeorwritablekey;//设置布尔值 是否可写

nsstring * const jspropertydeorenumerablekey;//设置布尔值 是否可枚举

nsstring * const jspropertydeorconfigurablekey;//设置布尔值 是否可配置

nsstring * const jspropertydeorvaluekey;//设置此属性的值

nsstring * const jspropertydeorgetkey;//设置此属性的get方法

nsstring * const jspropertydeorsetkey;//设置此属性的set方法

以上set、get方法的键和value、可写性的键不能同时存在,其语法是javascript保持一致

*/

- (void)defineproperty:(nsstring *)property deor:(id)deor;

//获取js数组对象某个下标的值

- (jsvalue *)valueatindex:(nsuinteger)index;

//设置js数组对象某个下标的值

- (void)setvalue:(id)value atindex:(nsuinteger)index;

//判断此对象是否为undefined

@property (readonly) bool isundefined;

//判断此对象是否为null

@property (readonly) bool isnull;

//判断此对象是否为布尔值

@property (readonly) bool isboolean;

//判断此对象是否为数值

@property (readonly) bool isnumber;

//判断此对象是否为字符串

@property (readonly) bool isstring;

//判断此对象是否为object对象

@property (readonly) bool isobject;

//判断此对象是否为数组

@property (readonly) bool isarray;

//判断此对象是否为日期对象

@property (readonly) bool isdate;

//比较两个jsvalue是否全相等 对应javascript中的===

- (bool)isequaltoobject:(id)value;

//比较两个jsvalue对象的值是否相等 对应javascript中的==

- (bool)isequalwithtypecoerciontoobject:(id)value;

//判断某个对象是否在当前对象的原型链上

- (bool)isinstanceof:(id)value;

//如果jsvalue是function对象 可以调用此方法 和javascript中的call方法一致

- (jsvalue *)callwitharguments:(nsarray *)arguments;

//如果jsvalue是一个构造方法对象 可以调用此方法 和javascript中使用new关键字一致

- (jsvalue *)constructwitharguments:(nsarray *)arguments;

//用此对象进行函数的调用 当前对象会被绑定到this中

- (jsvalue *)invokemethod:(nsstring *)method witharguments:(nsarray *)arguments;

//将cgpoint转换为jsvalue对象

(jsvalue *)valuewithpoint:(cgpoint)point incontext:(jscontext *)context;

//将nsrange转换为jsvalue对象

(jsvalue *)valuewithrange:(nsrange)range incontext:(jscontext *)context;

//将cgrect转换为jsvalue对象

(jsvalue *)valuewithrect:(cgrect)rect incontext:(jscontext *)context;

//将cgsize转换为jsvalue对象

(jsvalue *)valuewithsize:(cgsize)size incontext:(jscontext *)context;

//转换成cgpoint数据

- (cgpoint)topoint;

//转换成nsrange数据

- (nsrange)torange;

//转换成cgrect数据

- (cgrect)torect;

//转换为cgsize数据

- (cgsize)tosize;

//将c风格的jsvalueref对象转换为jsvalue对象

(jsvalue *)valuewithjsvalueref:(jsvalueref)value incontext:(jscontext *)context;

其实在javascriptcore框架中还有一个jsmanagervalue类,这个的主要作用是管理内存。虽然我们在编写objective-c代码时有强大的自动引用技术(arc技术),我们一般无需关心对象的内存问题,在编写javascript代码时也有强大的垃圾回收机制(这种机制下甚至连循环引用都不是问题),但是在oc和js混合开发时,就很容易出现问题了,比如一个js垃圾回收机制释放掉的对象oc中却还在用,反过来也是一样。jsmanagervalue对jsvalue进行了一层包装,它可以保证在适合时候使用这个对象时对象都不会被释放,其中方法如下:

//创建jsvlaue对象的包装jsmanagervalue

(jsmanagedvalue *)managedvaluewithvalue:(jsvalue *)value;

(jsmanagedvalue *)managedvaluewithvalue:(jsvalue *)value andowner:(id)owner;

- (instancetype)initwithvalue:(jsvalue *)value;

//获取所包装的jsvalue对象

@property (readonly, strong) jsvalue *value;

六、objective-c与javascript复杂对象的映射

? ? 我们在使用javascript调用objective-c方法的实质是将一个oc函数设置为了js全局对象的一个属性,当然我们也可以设置非函数的属性或者任意jsvalue(或者可以转换为jsvalue)的值。例如:

self.jscontext = [[jscontext alloc]init];

//向js全局对象中添加一个获取当前native设备类型的属性

[self.jscontext setobject:@"ios" forkeyedsub:@"devicetype"];

但是如果我们想把oc自定义的一个类的对象设置为js全局对象的某个属性,js和oc有着完全不同的对象原理,如果不做任何处理,js是接收不到oc对象中定义的属性和方法的。这时就需要使用到前面提到的jsexport协议,需要注意,这个协议不是用来被类遵守的,它里面没有规定任何方法,其是用来被继承定义新的协议的,自定义的协议中约定的方法和属性可以在js中被获取到,示例如下:

oc中新建一个自定义的类:

@protocol myobjectprotocol

@property(nonatomic,strong)nsstring * name;

@property(nonatomic,strong)nsstring * subject;

@property(nonatomic,assign)nsinteger age;

-(void)sayhi;

@end

@interface myobject : nsobject

@property(nonatomic,strong)nsstring * name;

@property(nonatomic,strong)nsstring * subject;

@property(nonatomic,assign)nsinteger age;

@end

@implementation myobject

-(void)sayhi{

nslog(@"hello javascript");

}

@end

添加到js全局对象中:

myobject* object = [myobject new];

object.name = @"jaki";

object.age = 25;

object.subject = @"oc";

[jscontext setobject:object forkeyedsub:@"deviceobject"];

在js运行环境中可以完整的到deviceobject对象,如下:

七、c语言风格的api解释

? ? javascriptcore框架中除了包含完整的objective-c和swift语言的api外,也提供了对c语言的支持。

? ? 与js运行环境相关的方法如下:

//创建一个jscontextref组

/*

jscontextref相当于jscontext,同一组中的数据可以共享

*/

jscontextgroupref jscontextgroupcreate(void);

//内存引用

jscontextgroupref jscontextgroupretain(jscontextgroupref group);

//内存引用释放

void jscontextgrouprelease(jscontextgroupref group);

//创建一个全局的运行环境

jsglobalcontextref jsglobalcontextcreate(jsclassref globalobjectclass);

//同上

jsglobalcontextref jsglobalcontextcreateingroup(jscontextgroupref group, jsclassref globalobjectclass);

//内存引用

jsglobalcontextref jsglobalcontextretain(jsglobalcontextref ctx);

//内存引用释放

void jsglobalcontextrelease(jsglobalcontextref ctx);

//获取全局对象

jsobjectref jscontextgetglobalobject(jscontextref ctx);

//获取jscontextref组

jscontextgroupref jscontextgetgroup(jscontextref ctx);

//获取全局的运行环境

jsglobalcontextref jscontextgetglobalcontext(jscontextref ctx);

//获取运行环境名

jsstringref jsglobalcontextcopyname(jsglobalcontextref ctx);

//设置运行环境名

void jsglobalcontextsetname(jsglobalcontextref ctx, jsstringref name);

? ? 与定义js对象的相关方法如下:

//定义js类

/*

参数jsclassdefinition是一个结构体 其中可以定义许多回调

*/

jsclassref jsclasscreate(const jsclassdefinition* definition);

//引用内存

jsclassref jsclassretain(jsclassref jsclass);

//释放内存

void jsclassrelease(jsclassref jsclass);

//创建一个js对象

jsobjectref jsobjectmake(jscontextref ctx, jsclassref jsclass, void* data);

//定义js函数

jsobjectref jsobjectmakefunctionwithcallback(jscontextref ctx, jsstringref name, jsobjectcallasfunctioncallback callasfunction);

//定义构造函数

jsobjectref jsobjectmakeconstructor(jscontextref ctx, jsclassref jsclass, jsobjectcallasconstructorcallback callasconstructor);

//定义数组

jsobjectref jsobjectmakearray(jscontextref ctx, size_t argumentcount, const jsvalueref arguments[], jsvalueref* exception);

//定义日期对象

jsobjectref jsobjectmakedate(jscontextref ctx, size_t argumentcount, const jsvalueref arguments[], jsvalueref* exception);

//定义异常对象

jsobjectref jsobjectmakeerror(jscontextref ctx, size_t argumentcount, const jsvalueref arguments[], jsvalueref* exception);

//定义正则对象

jsobjectref jsobjectmakeregexp(jscontextref ctx, size_t argumentcount, const jsvalueref arguments[], jsvalueref* exception);

//定义函数对象

jsobjectref jsobjectmakefunction(jscontextref ctx, jsstringref name, unsigned parametercount, const jsstringref parameternames[], jsstringref body, jsstringref sourceurl, int startinglinenumber, jsvalueref* exception);

//获取对象的属性

jsvalueref jsobjectgetprototype(jscontextref ctx, jsobjectref object);

//设置对象的属性

void jsobjectsetprototype(jscontextref ctx, jsobjectref object, jsvalueref value);

//检查对象是否包含某个属性

bool jsobjecthasproperty(jscontextref ctx, jsobjectref object, jsstringref propertyname);

//获取对象属性

jsvalueref jsobjectgetproperty(jscontextref ctx, jsobjectref object, jsstringref propertyname, jsvalueref* exception);

//定义对象属性

void jsobjectsetproperty(jscontextref ctx, jsobjectref object, jsstringref propertyname, jsvalueref value, jspropertyattributes attributes, jsvalueref* exception);

//删除对象属性

bool jsobjectdeleteproperty(jscontextref ctx, jsobjectref object, jsstringref propertyname, jsvalueref* exception);

//获取数组值

jsvalueref jsobjectgetpropertyatindex(jscontextref ctx, jsobjectref object, unsigned propertyindex, jsvalueref* exception);

//设置数组值

void jsobjectsetpropertyatindex(jscontextref ctx, jsobjectref object, unsigned propertyindex, jsvalueref value, jsvalueref* exception);

//获取私有数据

void* jsobjectgetprivate(jsobjectref object);

//设置私有数据

bool jsobjectsetprivate(jsobjectref object, void* data);

//判断是否为函数

bool jsobjectisfunction(jscontextref ctx, jsobjectref object);

//将对象作为函数来调用

jsvalueref jsobjectcallasfunction(jscontextref ctx, jsobjectref object, jsobjectref thisobject, size_t argumentcount, const jsvalueref arguments[], jsvalueref* exception);

//判断是否为构造函数

bool jsobjectisconstructor(jscontextref ctx, jsobjectref object);

//将对象作为构造函数来调用

jsobjectref jsobjectcallasconstructor(jscontextref ctx, jsobjectref object, size_t argumentcount, const jsvalueref arguments[], jsvalueref* exception);

//获取所有属性名

jspropertynamearrayref jsobjectcopypropertynames(jscontextref ctx, jsobjectref object);

//进行内存引用

jspropertynamearrayref jspropertynamearrayretain(jspropertynamearrayref array);

//内存释放

void jspropertynamearrayrelease(jspropertynamearrayref array);

//获取属性个数

size_t jspropertynamearraygetcount(jspropertynamearrayref array);

//在属性名数组中取值

jsstringref jspropertynamearraygetnameatindex(jspropertynamearrayref array, size_t index);

//添加属性名

void jspropertynameaccumulatoraddname(jspropertynameaccumulatorref accumulator, jsstringref propertyname);

? ? js数据类型相关定义在jsvalueref中,如下:

//获取值的类型

/*

枚举如下:

typedef enum {

kjstypeundefined,

kjstypenull,

kjstypeboolean,

kjstypenumber,

kjstypestring,

kjstypeobject

} jstype;

*/

jstype jsvaluegettype(jscontextref ctx, jsvalueref);

//判断是否为undefined类型

bool jsvalueisundefined(jscontextref ctx, jsvalueref value);

//判断是否为null类型

bool jsvalueisnull(jscontextref ctx, jsvalueref value);

//判断是否为布尔类型

bool jsvalueisboolean(jscontextref ctx, jsvalueref value);

//判断是否为数值类型

bool jsvalueisnumber(jscontextref ctx, jsvalueref value);

//判断是否为字符串类型

bool jsvalueisstring(jscontextref ctx, jsvalueref value);

//判断是否为对象类型

bool jsvalueisobject(jscontextref ctx, jsvalueref value);

//是否是类

bool jsvalueisobjectofclass(jscontextref ctx, jsvalueref value, jsclassref jsclass);

//是否是数组

bool jsvalueisarray(jscontextref ctx, jsvalueref value);

//是否是日期

bool jsvalueisdate(jscontextref ctx, jsvalueref value);

//比较值是否相等

bool jsvalueisequal(jscontextref ctx, jsvalueref a, jsvalueref b, jsvalueref* exception);

//比较值是否全等

bool jsvalueisstrictequal(jscontextref ctx, jsvalueref a, jsvalueref b);

//是否是某个类的实例

bool jsvalueisinstanceofconstructor(jscontextref ctx, jsvalueref value, jsobjectref constructor, jsvalueref* exception);

//创建undefined值

jsvalueref jsvaluemakeundefined(jscontextref ctx);

//创建null值

jsvalueref jsvaluemakenull(jscontextref ctx);

//创建布尔值

jsvalueref jsvaluemakeboolean(jscontextref ctx, bool boolean);

//创建数值

jsvalueref jsvaluemakenumber(jscontextref ctx, double number);

//创建字符串值

jsvalueref jsvaluemakestring(jscontextref ctx, jsstringref string);

//通过json创建对象

jsvalueref jsvaluemakefromjsonstring(jscontextref ctx, jsstringref string);

//将对象转为json字符串

jsstringref jsvaluecreatejsonstring(jscontextref ctx, jsvalueref value, unsigned indent, jsvalueref* exception);

//进行布尔值转换

bool jsvaluetoboolean(jscontextref ctx, jsvalueref value);

//进行数值转换

double jsvaluetonumber(jscontextref ctx, jsvalueref value, jsvalueref* exception);

//字符串值赋值

jsstringref jsvaluetostringcopy(jscontextref ctx, jsvalueref value, jsvalueref* exception);

//值与对象的转换

jsobjectref jsvaluetoobject(jscontextref ctx, jsvalueref value, jsvalueref* exception);

? ? 在c风格的api中,字符串也被包装成了jsstringref类型,其中方法如下:

//创建js字符串

jsstringref jsstringcreatewithcharacters(const jschar* chars, size_t numchars);

jsstringref jsstringcreatewithutf8cstring(const char* string);

//内存引用于释放

jsstringref jsstringretain(jsstringref string);

void jsstringrelease(jsstringref string);

//获取字符串长度

size_t jsstringgetlength(jsstringref string);

//转成utf8字符串

size_t jsstringgetutf8cstring(jsstringref string, char* buffer, size_t buffersize);

//字符串比较

bool jsstringisequal(jsstringref a, jsstringref b);

bool jsstringisequaltoutf8cstring(jsstringref a, const char* b);

八、hybird app 构建思路

? ? hybird app是指混合模式移动应用,即其中既包含原生的结构有内嵌有web的组件。这种app不仅性能和用户体验可以达到和原生所差无几的程度,更大的优势在于bug修复快,版本迭代无需发版。3月8日苹果给许多开发者发送了一封警告邮件,主要是提示开发者下载脚本动态更改app原本行为的做法将会被提审拒绝。其实这次邮件所提内容和hybird app并无太大关系(对reactnative也没有影响),苹果警告的是网络下发脚本并且使用runtime动态修改native行为的应用,hybird app的实质并没有修改原native的行为,而是将下发的资源进行加载和界面渲染,类似webview。

? ? 关于混合开发,我们有两种模式:

????1.native内嵌webview,通过js与oc交互实现业务无缝的衔接。

? ? 无论是uiwebview还是wkwebkit,我们都可以在其中拿到当前的jscontext,然是使用前面介绍的方法便可以实现数据互通与交互。这种方式是最简单的混合开发,但其性能和原生相比要差一些。示意图如下:

? ? 2.下发js脚本,使用类似reactnative的框架进行原生渲染

? ? 这是一种效率非常高的混合开发模式,并且reactnative也本身支持android和ios公用一套代码。我们也可以使用javascriptcore自己实现一套解析逻辑,使用javascript来编写native应用,要完整实现这样一套东西太复杂了,我们也没有能力完成一个如此庞大的工程,但是我们可以做一个小demo来模拟其原理,这样可以更好的帮助我们理解hybird app的构建原理。

我们打算实现这样的功能:通过下发js脚本创建原生的uilabel标签与uibutton控件,首先编写js代码如下:

(function(){

console.log("progectinit");

//js脚本加载完成后 自动render界面

return render();

})();

//js标签类

function label(rect,text,color){

this.rect = rect;

this.text = text;

this.color = color;

this.typename = "label";

}

//js按钮类

function button(rect,text,callfunc){

this.rect = rect;

this.text = text;

this.callfunc = callfunc;

this.typename = "button";

}

//js rect类

function rect(x,y,width,height){

this.x = x;

this.y = y;

this.width = width;

this.height = height;

}

//js颜色类

function color(r,g,b,a){

this.r = r;

this.g = g;

this.b = b;

this.a = a;

}

//渲染方法 界面的渲染写在这里面

function render(){

var rect = new rect(20,100,280,30);

var color = new color(1,0,0,1);

var label = new label(rect,"hello world",color);

var rect2 = new rect(20,150,280,30);

var color2 = new color(0,1,0,1);

var label2 = new label(rect2,"hello native",color2);

var rect3 = new rect(20,200,280,30);

var color3 = new color(0,0,1,1);

var label3 = new label(rect3,"hello javascript",color3);

var rect4 = new rect(20,240,280,30);

var button = new button(rect4,"我是一个按钮",function(){

var randcolor = new color(math.random(),math.random(),math.random(),1);

globle.changebackgroundcolor(randcolor);

});

//将控件以数组形式返回

return [label,label2,label3,button];

}

创建一个objective-c类绑定到js全局对象上,作为oc方法的桥接器:

//.h

#import

#import

#import

@protocol globleprptocol

-(void)changebackgroundcolor:(jsvalue *)value;

@end

@interface globle : nsobject

@property(nonatomic,weak)uiviewcontroller * ownercontroller;

@end

//.m

#import "globle.h"

@implementation globle

-(void)changebackgroundcolor:(jsvalue *)value{

self.ownercontroller.view.backgroundcolor = [uicolor colorwithred:value[@"r"].todouble green:value[@"g"].todouble blue:value[@"b"].todouble alpha:value[@"a"].todouble];

}

@end

在viewcontroller中实现一个界面渲染的render解释方法,并建立按钮的方法转换,如下:

//

// viewcontroller.m

// javascriptcoretest

//

// created by vip on 17/3/6.

// 威尼斯人2299 copyright ? 2017年 jaki. all rights reserved.

//

#import "viewcontroller.h"

#import

#import "globle.h"

@interface viewcontroller ()

@property(nonatomic,strong)jscontext * jscontext;

@property(nonatomic,strong)nsmutablearray * actionarray;

@property(nonatomic,strong)globle * globle;

@end

@implementation viewcontroller

- (void)viewdidload {

[super viewdidload];

//创建js运行环境

self.jscontext = [jscontext new];

//绑定桥接器

self.globle = [globle new];

self.globle.ownercontroller = self;

self.jscontext[@"globle"] = self.globle;

self.actionarray = [nsmutablearray array];

[self render];

}

//界面渲染解释器

-(void)render{

nsstring * path = [[nsbundle mainbundle] pathforresource:@"main" oftype:@"js"];

nsdata * jsdata = [[nsdata alloc]initwithcontentsoffile:path];

nsstring * jscode = [[nsstring alloc]initwithdata:jsdata encoding:nsutf8stringencoding];

jsvalue * jsvlaue = [self.jscontext evaluatescript:jscode];

for (int i=0; i

jsvalue * subvalue = [jsvlaue objectatindexedsub:i];

if ([[subvalue objectforkeyedsub:@"typename"].tostring isequaltostring:@"label"]) {

uilabel * label = [uilabel new];

label.frame = cgrectmake(subvalue[@"rect"][@"x"].todouble, subvalue[@"rect"][@"y"].todouble, subvalue[@"rect"][@"width"].todouble, subvalue[@"rect"][@"height"].todouble);

label.text = subvalue[@"text"].tostring;

label.textcolor = [uicolor colorwithred:subvalue[@"color"][@"r"].todouble green:subvalue[@"color"][@"g"].todouble blue:subvalue[@"color"][@"b"].todouble alpha:subvalue[@"color"][@"a"].todouble];

[self.view addsubview:label];

}else if ([[subvalue objectforkeyedsub:@"typename"].tostring isequaltostring:@"button"]){

uibutton * button = [uibutton buttonwithtype:uibuttontypesystem];

button.frame = cgrectmake(subvalue[@"rect"][@"x"].todouble, subvalue[@"rect"][@"y"].todouble, subvalue[@"rect"][@"width"].todouble, subvalue[@"rect"][@"height"].todouble);

[button settitle:subvalue[@"text"].tostring forstate:uicontrolstatenormal];

button.tag = self.actionarray.count;

[button addtarget:self action:@selector(buttonaction:) forcontrolevents:uicontroleventtouchupinside];

[self.actionarray addobject:subvalue[@"callfunc"]];

[self.view addsubview:button];

}

}

}

//按钮转换方法

-(void)buttonaction:(uibutton *)btn{

jsvalue * action = self.actionarray[btn.tag];

//执行js方法

[action callwitharguments:nil];

}

@end

运行工程,效果如下图所示,点击按钮即可实现简单的界面颜色切换:

上面的示例工程我只实现了uilabel类与uibutton类的js-oc转换,如果将原生控件和js对象再进行一层绑定,并且实现大部分js类与原生类和他们内部的属性,则我们就开发了一套hybird app开发框架,但并没有这个必要,如果你对更多兴趣,可以深入学习下reactnative。

? ? 文中的示例demo我放在了github上,地址如下:github - zyhshao/demo-hybird: 混合开发在ios中的构建思路demo。

前端学习新人,有志同道合的朋友,欢迎交流与指导,qq群:541458536

转载于: my.oschina /u/2340880/blog/856321

文章威尼斯人2299的版权声明:除非注明,否则均为网络节点原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
addoilapplausebadlaughbombcoffeefabulousfacepalmfecesfrownheyhainsidiouskeepfightingnoprobpigheadshockedsinistersmileslapsocialsweattolaughwatermelonwittywowyeahyellowdog
评论列表 (暂无评论,35人围观)

还没有评论,来说两句吧...

网站地图