曾经想要oc调用js代码通常是通过uiwebview的stringByEvaluatingJavaScriptFromString方法,或是直接使用JavaScriptCore引擎,比如https://github.com/jfahrenkrug/AddressBookSpy。

可是,Apple正式公布了新的iOS 7系统,引入了JavaScriptCore.framework
 ,最大最直观的改变在于界面变得小清新范了,我也提到《iOS,你真的越来越像Android了》。只是对于移动开发人员来说,除了要适应Xcode
5,最应该关注的还是iOS 7在开发接口的上的变化。概览Apple提供的官方文档《What’s New in iOS》,最最让我欣喜的是iOS
7中增加了JavaScriptCore框架。该框架让Objective-C和JavaScript代码直接的交互变得更加的简单方便。

这个框架事实上仅仅是基于webkit中以C/C++实现的JavaScriptCore的一个包装,在旧版本号iOS开发中,非常多开发人员也会自行将webkit的库引入项目编译使用。只是尽管iOS7把它当成了标准库,可惜眼下,我还没有在Apple Developer中找到像之前文章中收集的那样的官方文档介绍这个框架的详细用法。

好在还能够在Xcode中找到头文件,并且里面的凝视对每一个类和方法的功能写得还算清楚,再结合网上仅有的几篇文章的介绍,我也在此简单入门一下JavaScriptCore。很多其它细节还待开发过程中发现。

JavaScriptCore中的类



在项目中引入JavaScriptCore后,链到头文件中,除了大段的Copyright凝视能够看到里面仅仅要引入了5个文件,每一个文件中都定义跟文件名称相应的类:

  • JSContext
  • JSValue
  • JSManagedValue
  • JSVirtualMachine
  • JSExport

虽说代码中的凝视介绍的也比較具体了,可是如同一图顶万言,对程序猿来说代码更有说服力。本文就先来说说这些类相对照较好理解但又非经常常使用的JSContext和JSValue以及它们方法的使用方式和效果。

JSContext和JSValue

JSVirtualMachine为JavaScript的执行提供了底层资源,JSContext就为其提供着执行环境,通过-
(JSValue *)evaluateScript:(NSString *)script;
方法就能够运行一段JavaScript脚本,而且假设当中有方法、变量等信息都会被存储在当中以便在须要的时候使用。而JSContext的创建都是基于JSVirtualMachine-
(id)initWithVirtualMachine:(JSVirtualMachine *)virtualMachine;
,假设是使用-
(id)init;
进行初始化,那么在其内部会自己主动创建一个新的JSVirtualMachine对象然后调用前边的初始化方法。

JSValue则能够说是JavaScript和Object-C之间互换的桥梁,它提供了多种方法能够方便地把JavaScript数据类型转换成Objective-C,或者是转换过去。其一一相应方式可见下表:

 

Objective-C JavaScript JSValue Convert JSValue Constructor

nil undefined   valueWithUndefinedInContext
NSNull null   valueWithNullInContext:
NSString string toString  
NSNumber number, boolean toNumber

toBool

toDouble

toInt32

toUInt32
valueWithBool:inContext:

valueWithDouble:inContext:

valueWithInt32:inContext:

valueWithUInt32:inContext:
NSDictionary Object object toDictionary valueWithNewObjectInContext:
NSArray Array object toArray valueWithNewArrayInContext:
NSDate Date object toDate  
NSBlock Function object    
id Wrapper object toObject

toObjectOfClass:
valueWithObject:inContext:
Class Constructor object    

基本类型转换

先看个简单的样例:

  1. JSContext *context = [[JSContext
    alloc] init];
  2. JSValue *jsVal = [context
    evaluateScript:@"21+7"];
  3. int iVal = [jsVal
    toInt32];
  4. NSLog(@"JSValue:
    %@, int: %d", jsVal, iVal);
  5.  
  6. //Output:
  7. // JSValue: 28, int: 28

非常easy吧,还能够存一个JavaScript变量在JSContext中,然后通过下标来获取出来。而对于Array或者Object类型,JSValue也能够通过下标直接取值和赋值。

  1. JSContext *context = [[JSContext
    alloc] init];
  2. [context evaluateScript:@"var
    arr = [21, 7 , 'iderzheng.com'];"];
  3. JSValue *jsArr = context[@"arr"]; //
    Get array from JSContext
  4.  
  5. NSLog(@"JS
    Array: %@; Length: %@", jsArr, jsArr[@"length"]);
  6. jsArr[1] = @"blog"; //
    Use JSValue as array
  7. jsArr[7] = @7;
  8.  
  9. NSLog(@"JS
    Array: %@; Length: %d", jsArr, [jsArr[@"length"] toInt32]);
  10.  
  11. NSArray *nsArr = [jsArr
    toArray];
  12. NSLog(@"NSArray:
    %@", nsArr);
  13.  
  14. //Output:
  15. // JS Array: 21,7,iderzheng.com Length: 3
  16. // JS Array: 21,blog,iderzheng.com,,,,,7 Length: 8
  17. // NSArray: (
  18. // 21,
  19. // blog,
  20. // "iderzheng.com",
  21. // "<null>",
  22. // "<null>",
  23. // "<null>",
  24. // "<null>",
  25. // 7
  26. // )

通过输出结果非常easy看出代码成功把数据从Objective-C赋到了JavaScript数组上,并且JSValue是遵循JavaScript的数组特性:无下标越位,自己主动延展数组大小。并且通过JSValue还能够获取JavaScript对象上的属性,比方样例中通过"length"就获取到了JavaScript数组的长度。在转成NSArray的时候,全部的信息也都正确转换了过去。

方法的转换

各种数据类型能够转换,Objective-C的Block也能够传入JSContext中当做JavaScript的方法使用。比方在前端开发中经常使用的log方法,尽管JavaScritpCore没有自带(毕竟不是在网页上执行的,自然不会有window、document、console这些类了),仍然能够定义一个Block方法来调用NSLog来模拟:

  1. JSContext *context = [[JSContext
    alloc] init];
  2. context[@"log"] = ^() {
  3. NSLog(@"+++++++Begin
    Log+++++++");
  4.  
  5. NSArray *args = [JSContext
    currentArguments];
  6. for (JSValue *jsVal in args) {
  7. NSLog(@"%@",
    jsVal);
  8. }
  9.  
  10. JSValue *this = [JSContext
    currentThis];
  11. NSLog(@"this:
    %@",this);
  12. NSLog(@"-------End
    Log-------");
  13. };
  14.  
  15. [context evaluateScript:@"log('ider',
    [7, 21], { hello:'world', js:100 });"];
  16.  
  17. //Output:
  18. // +++++++Begin Log+++++++
  19. // ider
  20. // 7,21
  21. // [object Object]
  22. // this: [object GlobalObject]
  23. // -------End Log-------

通过Block成功的在JavaScript调用方法回到了Objective-C,并且依旧遵循JavaScript方法的各种特点,比方方法參数不固定。也由于这样,JSContext提供了类方法来获取參数列表(+
(JSContext *) currentArguments;
)和当前调用该方法的对象(+
(JSValue *)currentThis
)。对于"this",输出的内容是GlobalObject,这也是JSContext对象方法-
(JSValue *)globalObject;
所返回的内容。由于我们知道在JavaScript里,全部全局变量和方法事实上都是一个全局变量的属性,在浏览器中是window,在JavaScriptCore是什么就不得而知了。

Block能够传入JSContext作方法,可是JSValue没有toBlock方法来把JavaScript方法变成Block在Objetive-C中使用。毕竟Block的參数个数和类型已经返回类型都是固定的。尽管不能把方法提取出来,可是JSValue提供了-
(JSValue *)callWithArguments:(NSArray *)arguments;
方法能够反过来将參数传进去来调用方法。

  1. JSContext *context = [[JSContext
    alloc] init];
  2. [context evaluateScript:@"function
    add(a, b) { return a + b; }"];
  3. JSValue *add = context[@"add"];
  4. NSLog(@"Func:
    %@", add);
  5.  
  6. JSValue *sum = [add
    callWithArguments:@[@(7),
    @(21)]];
  7. NSLog(@"Sum:
    %d",[sum toInt32]);
  8. //OutPut:
  9. // Func: function add(a, b) { return a + b; }
  10. // Sum: 28

JSValue还提供-
(JSValue *)invokeMethod:(NSString *)method withArguments:(NSArray *)arguments;
让我们能够直接简单地调用对象上的方法。仅仅是假设定义的方法是全局函数,那么非常显然应该在JSContextglobalObject对象上调用该方法;假设是某JavaScript对象上的方法,就应该用对应的JSValue对象调用。

异常处理

Objective-C的异常会在执行时被Xcode捕获,而在JSContext中执行的JavaScript假设出现异常,仅仅会被JSContext捕获并存储在exception属性上,而不会向外抛出。时时刻刻检查JSContext对象的exception是否不为nil显然是不合适,更合理的方式是给JSContext对象设置exceptionHandler,它接受的是^(JSContext
*context, JSValue *exceptionValue)
形式的Block。其默认值就是将传入的exceptionValue赋给传入的contextexception属性:

  1. ^(JSContext *context,
    JSValue *exceptionValue) {
  2. context.exception = exceptionValue;
  3. };

我们也能够给exceptionHandler赋予新的Block以便在JavaScript执行发生异常的时候我们能够马上知道:

  1. JSContext *context = [[JSContext
    alloc] init];
  2. context.exceptionHandler = ^(JSContext *con,
    JSValue *exception) {
  3. NSLog(@"%@",
    exception);
  4. con.exception = exception;
  5. };
  6.  
  7. [context evaluateScript:@"ider.zheng
    = 21"];
  8.  
  9. //Output:
  10. // ReferenceError: Can't find variable: ider

使用Block的注意事项

从之前的样例和介绍应该有体会到Block在JavaScriptCore中起到的强大作用,它在JavaScript和Objective-C之间的转换 建立起很多其它的桥梁,让互通更方便。可是要注意的是不管是把Block传给JSContext对象让其变成JavaScript方法,还是把它赋给exceptionHandler属性,在Block内都不要直接使用其外部定义的JSContext对象或者JSValue,应该将其当做參数传入到Block中,或者通过JSContext的类方法+
(JSContext *)currentContext;
来获得。否则会造成循环引用使得内存无法被正确释放。

比方上边自己定义异常处理方法,就是赋给传入JSContext对象con,而不是其外创建的context对象,尽管它们事实上是同一个对象。这是由于Block会对内部使用的在外部定义创建的对象做强引用,而JSContext也会对被赋予的Block做强引用,这样它们之间就形成了循环引用(Circular
Reference
)使得内存无法正常释放。

对于JSValue也不能直接从外部引用到Block中,由于每一个JSValue上都有JSContext的引用
(@property(readonly, retain)
JSContext *context;
),JSContext再引用Block相同也会形成引用循环。

前面十分的简单方便并且高效,只是也仅限于数值型、布尔型、字符串、数组等这些基础类型。本文将扩展到更复杂的类型,介绍一下该强大的框架是怎样让Objective-C对象和JavaScript对象进行直接互通的。

为了方便起见,下面全部代码中的JSContext对象都会加入例如以下的log方法和eventHandler

  1. JSContext *context = [[JSContext
    alloc] init];
  2. context.exceptionHandler = ^(JSContext *con,
    JSValue *exception) {
  3. NSLog(@"%@",
    exception);
  4. con.exception = exception;
  5. };
  6.  
  7. context[@"log"] = ^() {
  8. NSArray *args = [JSContext
    currentArguments];
  9. for (id obj in args) {
  10. NSLog(@"%@",obj);
  11. }
  12. };

键值对编程—Dictionary

JSContext并不能让Objective-C和JavaScript的对象直接转换,毕竟两者的面向对象的设计方式是不同的:前者基于class,后者基于prototype。但全部的对象事实上能够视为一组键值对的集合,所以JavaScript中的对象能够返回到Objective-C中当做NSDictionary类型进行訪问。

  1. JSValue *obj =[context
    evaluateScript:@"var
    jsObj = { number:7, name:'Ider' }; jsObj"];
  2. NSLog(@"%@,
    %@", obj[@"name"],
    obj[@"number"]);
  3. NSDictionary *dic = [obj
    toDictionary];
  4. NSLog(@"%@,
    %@", dic[@"name"],
    dic[@"number"]);
  5. //Output:
  6. // Ider, 7
  7. // Ider, 7

相同的,NSDicionaryNSMutableDictionary传入到JSContext之后也能够直接当对象来调用:

  1. NSDictionary *dic = @{@"name": @"Ider", @"#":@(21)};
  2. context[@"dic"] = dic;
  3. [context evaluateScript:@"log(dic.name,
    dic['#'])"];
  4. //OutPut:
  5. // Ider
  6. // 21

语言穿梭机—JSExport协议

JavaScript能够脱离prototype继承全然用JSON来定义对象,可是Objective-C编程里可不能脱离类和继承了写代码。所以JavaScriptCore就提供了JSExport作为两种语言的互通协议。JSExport中没有约定不论什么的方法,连可选的(@optional)都没有,可是全部继承了该协议(@protocol)的协议(注意不是Objective-C的类(@interface))中定义的方法,都能够在JSContext中被使用。语言表述起来有点绕,还是用样例来说明会更明白一点。

  1. @protocol PersonProtocol <JSExport>
  2.  
  3. @property (nonatomic,
    retain) NSDictionary *urls;
  4. - (NSString *)fullName;
  5.  
  6. @end
  7.  
  8. @interface Person :NSObject <PersonProtocol>
  9.  
  10. @property (nonatomic,
    copy) NSString *firstName;
  11. @property (nonatomic,
    copy) NSString *lastName;
  12.  
  13. @end;
  14.  
  15. @implementation Person
  16.  
  17. @synthesize firstName, lastName, urls;
  18.  
  19. - (NSString *)fullName {
  20. return [NSString stringWithFormat:@"%@
    %@", self.firstName, self.lastName];
  21. }
  22.  
  23. @end

在上边的代码中,定义了一个PersonProtocol,并让它继承了神奇的JSExport协议,在新定义的协议中约定urls属性和fullName方法。之后又定义了Person类,除了让它实现PersonProtocol外,还定义了firstName和lastName属性。而fullName方法返回的则是两部分名字的结合。

下边就来创建一个Person对象,然后传入到JSContext中并尝试使用JavaScript来訪问和改动该对象。

  1. // initialize person object
  2. Person *person = [[Person
    alloc] init];
  3. context[@"p"] = person;
  4. person.firstName = @"Ider";
  5. person.lastName = @"Zheng";
  6. person.urls = @{@"site": @"http://www.iderzheng.com"};
  7.  
  8. // ok to get fullName
  9. [context evaluateScript:@"log(p.fullName());"];
  10. // cannot access firstName
  11. [context evaluateScript:@"log(p.firstName);"];
  12. // ok to access dictionary as object
  13. [context evaluateScript:@"log('site:',
    p.urls.site, 'blog:', p.urls.blog);"];
  14. // ok to change urls property
  15. [context evaluateScript:@"p.urls
    = {blog:'http://blog.iderzheng.com'}"];
  16. [context evaluateScript:@"log('-------AFTER
    CHANGE URLS-------')"];
  17. [context evaluateScript:@"log('site:',
    p.urls.site, 'blog:', p.urls.blog);"];
  18.  
  19. // affect on Objective-C side as well
  20. NSLog(@"%@",
    person.urls);
  21.  
  22. //Output:
  23. // Ider Zheng
  24. // undefined
  25. // undefined
  26. // site:
  27. // http://www.iderzheng.com
  28. // blog:
  29. // undefined
  30. // -------AFTER CHANGE URLS-------
  31. // site:
  32. // undefined
  33. // blog:
  34. // http://blog.iderzheng.com
  35. // {
  36. // blog = "http://blog.iderzheng.com";
  37. // }

从输出结果不难看出,当訪问firstNamelastName的时候给出的结果是undefined,由于它们跟JavaScript没有JSExport的联系。但这并不影响从fullName()中正确得到两个属性的值。和之前说过的一样,对于NSDictionary类型的urls,能够在JSContext中当做对象使用,并且还能够正确地给urls赋予新的值,并反映到实际的Objective-C的Person对象上。

JSExport不仅能够正确反映属性到JavaScript中,并且对属性的特性也会保证其正确,比方一个属性在协议中被声明成readonly,那么在JavaScript中也就仅仅能读取属性值而不能赋予新的值。

对于多參数的方法,JavaScriptCore的转换方式将Objective-C的方法每一个部分都合并在一起,冒号后的字母变为大写并移除冒号。比方下边协议中的方法,在JavaScript调用就是:doFooWithBar(foo,
bar);

  1. @protocol MultiArgs <JSExport>
  2. - (void)doFoo:(id)foo
    withBar:(id)bar;
  3. @end

假设希望方法在JavaScript中有一个比較短的名字,就须要用的JSExport.h中提供的宏:JSExportAs(PropertyName,
Selector)

  1. @protocol LongArgs <JSExport>
  2.  
  3. JSExportAs(testArgumentTypes,
  4. - (NSString *)testArgumentTypesWithInt:(int)i double:(double)d
  5. boolean:(BOOL)b string:(NSString *)s
    number:(NSNumber *)n
  6. array:(NSArray *)a
    dictionary:(NSDictionary *)o
  7. );
  8.  
  9. @end

比方上边定义的协议中的方法,在JavaScript就仅仅要用testArgumentTypes(i,
d, b, s, n, a, dic);
来调用就能够了。

尽管JavaScriptCore框架还没有官方编程指南,可是在JSExport.h文件里对神奇协议的表述还是比較具体的,当中有一条是这样描写叙述的:

By default no methods or properties of the Objective-C class will be exposed to JavaScript, however methods and properties may explicitly be exported. For each protocol that a class conforms to, if the protocol incorporates the protocol JSExport, then the protocol
will be interpreted as a list of methods and properties to be exported to JavaScript.

这里面有个incorporate一词值得推敲,经过验证仅仅有直接继承了JSExport的自己定义协议(@protocol)才干在JSContext中訪问到。也就是说比方有其他的协议继承了上边的PersonProtocol,当中的定义的方法并不会被引入到JSContext中。从源代码中也能看出JavaScriptCore框架会通过class_copyProtocolList方法找到类所遵循的协议,然后再对每一个协议通过protocol_copyProtocolList检查它是否遵循JSExport协议进而将方法反映到JavaScript之中。

对已定义类扩展协议— class_addProtocol

对于自己定义的Objective-C类,能够通过之前的方式自己定义继承了JSExport的协议来实现与JavaScript的交互。对于已经定义好的系统类或者从外部引入的库类,她们都不会预先定义协议提供与JavaScript的交互的。好在Objective-C是能够在执行时实行对类性质的改动的

比方下边的样例,就是为UITextField加入了协议,让其能在JavaScript中能够直接訪问text属性。该接口例如以下:

  1. @protocol JSUITextFieldExport <JSExport>
  2.  
  3. @property(nonatomic,copy) NSString *text;
  4.  
  5. @end

之后在通过class_addProtocol为其加入上该协议:

  1. - (void)viewDidLoad {
  2. [super viewDidLoad];
  3.  
  4. textField.text = @"7";
  5. class_addProtocol([UITextField
    class], @protocol(JSUITextFieldExport));
  6. }

为一个UIButton加入例如以下的事件,其方法仅仅要是将textField传入到JSContext中然后读取其text值,自增1后又一次赋值:

  1. - (IBAction)pressed:(id)sender {
  2. JSContext *context = [[JSContext
    alloc] init];
  3.  
  4. context[@"textField"] = textField;
  5.  
  6. NSString *script = @"var
    num = parseInt(textField.text, 10);"
  7. "++num;"
  8. "textField.text = num;";
  9. [context evaluateScript:script];
  10. }

当执行点击UIButton时就会看到UITextField的值在不断添加,也证明了对于已定义的类,也能够在执行时加入奇妙的JSExport协议让它们能够在Objective-C和JavaScript直接实现友好互通。

 

不同内存管理机制—Reference Counting vs. Garbage Collection

尽管Objetive-C和JavaScript都是面向对象的语言,并且它们都能够让程序猿专心于业务逻辑,不用操心内存回收的问题。可是两者的内存回首机制全是不同的,Objective-C是基于引用计数,之后Xcode编译器又支持了自己主动引用计数(ARC, Automatic Reference
Counting)
;JavaScript则如同Java/C#那样用的是垃圾回收机制(GC, Garbage Collection)。当两种不同的内存回收机制在同一个程序中被使用时就难免会产生冲突。

比方,在一个方法中创建了一个暂时的Objective-C对象,然后将其增加到JSContext放在JavaScript中的变量中被使用。由于JavaScript中的变量有引用所以不会被释放回收,可是Objective-C上的对象可能在方法调用结束后,引用计数变0而被回收内存,因此JavaScript层面也会造成错误訪问。

相同的,假设用JSContext创建了对象或者数组,返回JSValue到Objective-C,即使把JSValue变量retain下,但可能由于JavaScript中由于变量没有了引用而被释放内存,那么相应的JSValue也没实用了。

怎么在两种内存回收机制中处理好对象内存就成了问题。JavaScriptCore提供了JSManagedValue类型帮助开发者更好地管理对象内存。

  1. @interface JSManagedValue : NSObject
  2.  
  3. // Convenience method for creating JSManagedValues from JSValues.
  4. + (JSManagedValue *)managedValueWithValue:(JSValue *)value;
  5.  
  6. // Create a JSManagedValue.
  7. - (id)initWithValue:(JSValue *)value;
  8.  
  9. // Get the JSValue to which this JSManagedValue refers. If the JavaScript value has been collected,
  10. // this method returns nil.
  11. - (JSValue *)value;
  12.  
  13. @end

在《iOS7新JavaScriptCore框架入门介绍》有提到JSVirtualMachine为整个JavaScriptCore的执行提供资源,所以当将一个JSValue转成JSManagedValue后,就能够加入到JSVirtualMachine中,这样在执行期间就能够保证在Objective-C和JavaScript两側都能够正确訪问对象而不会造成不必要的麻烦。

  1. @interface JSVirtualMachine : NSObject
  2.  
  3. // Create a new JSVirtualMachine.
  4. - (id)init;
  5.  
  6. // addManagedReference:withOwner and removeManagedReference:withOwner allow
  7. // clients of JSVirtualMachine to make the JavaScript runtime aware of
  8. // arbitrary external Objective-C object graphs. The runtime can then use
  9. // this information to retain any JavaScript values that are referenced
  10. // from somewhere in said object graph.
  11. //
  12. // For correct behavior clients must make their external object graphs
  13. // reachable from within the JavaScript runtime. If an Objective-C object is
  14. // reachable from within the JavaScript runtime, all managed references
  15. // transitively reachable from it as recorded with
  16. // addManagedReference:withOwner: will be scanned by the garbage collector.
  17. //
  18. - (void)addManagedReference:(id)object
    withOwner:(id)owner;
  19. - (void)removeManagedReference:(id)object
    withOwner:(id)owner;
  20.  
  21. @end

ios7 JavaScriptCore.framework的更多相关文章

  1. iOS中JS 与OC的交互(JavaScriptCore.framework)

    iOS中实现js与oc的交互,目前网上也有不少流行的开源解决方案: 如:react native 当然一些轻量级的任务使用系统提供的UIWebView 以及JavaScriptCore.framewo ...

  2. iOS开发:JavaScriptCore.framework的简单使用--JS与OC的交互篇

    iOS7之后苹果为众猿推出了JavaScriptCore.framework这个框架,这个框架为大家在与JS交互上提供了很大帮助,可以在html界面上调用OC方法并传参,也可以在OC上调用JS方法并传 ...

  3. JavaScriptCore.framework基本用法(一)

    从iOS7开始 苹果公布了JavaScriptCore.framework 它使得JS与OC的交互更加方便了. 下面我们就简单了解一下这个框架 首先我导入framework 方法如下 点击Linked ...

  4. JavaScriptCore.framework基本用法(二)

    接着上节我们讲到的iOS调用js 下来我们使用js调用iOS js调用iOS分两种情况 一,js里面直接调用方法 二,js里面通过对象调用方法 首先我们看第一种,直接调用方法. 其中用到了iOS的bl ...

  5. WebView与JS的几种交互

    http://www.jianshu.com/p/0042d8eb67c0 最近整理了一下原生与H5之间的交互方式,简单的做个总结.OC端与JS的交互,大致有这几种:拦截协议.JavaScriptCo ...

  6. ios中javascript直接调用oc代码而非通过改变url回调方式(转)

    之前一个ios项目中,需要通过UIWebview来打开一个静态页面,并在静态页面中 调用相关object-c代码. 一.以前使用js调用object-c的方法 关于如何使用javascript调用ob ...

  7. OC和JS的交互---JavaScriptCore

    JavaScriptCore的简单介绍 JavaScriptCore是iOS7提供的原生框架,可以让Objective-C和JavaScript提供简单直接的交互. JavaScriptCore的使用 ...

  8. iOS js oc相互调用JavaScriptCore(一)

    原址:http://blog.csdn.net/lwjok2007/article/details/47058101 1.普通调用 从iOS7开始 苹果公布了JavaScriptCore.framew ...

  9. iOS下JS与OC互相调用(四)--JavaScriptCore

    前面讲完拦截URL的方式实现JS与OC互相调用,终于到JavaScriptCore了.它是从iOS7开始加入的,用 Objective-C 把 WebKit 的 JavaScript 引擎封装了一下, ...

随机推荐

  1. Eclipse+Maven命令创建webapp项目<三>

    1.使用maven命令:mvn archetype:create -DgroupId=xxxxx -DartifactId=web-sample -DarchetypeArtifactId=maven ...

  2. ASP.NET Core 1.0 部署 HTTPS

    ASP.NET Core 1.0 部署 HTTPS ASP.NET Core 1.0 部署 HTTPS (.NET Framework 4.5.1) 提示 更新时间:2016年01月23日. 在目前介 ...

  3. ASF(传感器)

    版权声明:曾经的Blog文章合并.原创作品,谢绝转载.否则将追究法律责任. SensorManager类:用于创建sensor service的实例.该类提供了非常多 用于訪问和枚举传感器,注冊和注销 ...

  4. uva 10817 Headmaster&#39;s Headache 出发dp 位计算

    出发dp,用在一些议题的操作非常~  给出s个课程.m个教师.n个求职者,教师必须招聘.然后招聘一些求职者,使得每一门课都至少有两个老师能教.问题就转换成了招聘哪些求职者使得花费最少.由于s范围小于8 ...

  5. Windows Azure应用系列:微软的云部署VPN

    本文介绍如何使用OpenVPN微软云计算server既定VPN维修. 过程,如下面: 1.新建Linux或者Ubuntu虚拟机.并设置port.(本文将建立Ubuntu作为演示) 2.利用PuTTY登 ...

  6. iOS 中client和server的 Web Service 网络通信 (2)

    在实际的应用开发过程中,同步请求的用户体验并非非常好:我们都知道.Apple是非常重视用户体验的.这一点也成为了行业的标杆,没实用户哪里来的好产品.所以用户体验是极其重要的.貌似废话有点多.接下来进入 ...

  7. BZOJ 1052 HAOI2007 覆盖问题 二分法答案+DFS

    标题效果:特定n点.涵盖所有的点与同方三面.斧头要求方垂直边界,最小平方的需求方长值 最大值至少.答案是很明显的二分法 但验证是一个问题 考虑仅仅有三个正方形,故用一个最小矩形覆盖这三个正方形时至少有 ...

  8. Multicast on Openstack

    I test multicast on openstack. I use external Router in this test. Openstack Environment: Havana (ML ...

  9. zoj 1738 - Lagrange&#39;s Four-Square Theorem

    称号:四方形定理.输出可以表示为一个数目不超过四个平方和表示的数. 分析:dp,完全背包.背包分割整数.可用一维分数计算,它也可以被写为一个二维团结. 状态:设f(i,j,k)为前i个数字,取j个数字 ...

  10. 用DOS命令获取文件列表

    其实就是两个命令:dir 跟 tree 在C:盘根目录下生成了一个名为“filelist.txt”的文本文件,该文件中即包含D:盘的文件夹列表. dir d:\ >c:\filelist.txt ...