2014-07-06 91 views
7

我一直在想如何在快速使用JavaScriptCore。但是,当我必须将块作为参数进行处理时,我遇到了问题,好像块立即运行并且参数获得块的返回值。我究竟做错了什么?快速块不能正常工作

工作目标C代码:

JSContext* context = [[JSContext alloc] initWithVirtualMachine:[[JSVirtualMachine alloc] init]]; 
context[@"test"] = ^(NSString *string) { 
    //code 
}; 

我已经试过:

1:

var ctx = JSContext(virtualMachine:JSVirtualMachine()) 
var ctx["test"] = {(string:NSString)->() in /*code*/ } 

//Gives me "'JSContext' does not have a member named 'subscript'" 

2:

​​

3:

var ctx = JSContext(virtualMachine:JSVirtualMachine()) 
let n: (string: String)->() = {string in /*code*/} 

ctx.setObject(n as AnyObject, forKeyedSubscript:"test") 

//Gives me "Cannot downcast from '(string: String) ->() to [email protected] protocol type 'AnyObject'" 

我在这里错过了什么,或者这只是Swift中的一个错误?

编辑:从Cast closures/blocks

class Block<T> { 
    let f : T 
    init (_ f: T) { self.f = f } 
} 

现在我也试着建议,然后

ctx.setObject(Block<()->Void> { 
     /*code*/ 
    }, forKeyedSubscript: "test") 

该解决方案让我编译,但我得到一个运行时错误:

Thread 1: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0) 
+0

似乎是这个问题:http://stackoverflow.com/questions/24586293/cast-closures-blocks。 –

+0

它是相似但不同。这个问题是关于处理你从* Objc方法作为返回值*得到的块。这是关于传递Swift闭包作为块*到* Objc方法。 –

回答

26

它与Swift如何实现闭包有关。您需要使用@convention(block)来注释闭包是ObjC块。使用unsafeBitCast迫使投它

var block : @convention(block) (NSString!) -> Void = { 
    (string : NSString!) -> Void in 
    println("test") 
} 

ctx.setObject(unsafeBitCast(block, AnyObject.self), forKeyedSubscript: "test") 

从REPL

swift 
Welcome to Swift! Type :help for assistance. 
    1> import Foundation 
    2> var block : @convention(block)(NSString!) -> Void = {(string : NSString!) -> Void in println("test")} 
block: @convention(block)(NSString!) -> Void = 
    3> var obj: AnyObject = reinterpretCast(block) as AnyObject 
obj: __NSMallocBlock__ = {} // familiar block type 
+0

这就像一个魅力!非常感谢。只有一件事,显然'ctx [“test”] ='不起作用。然而'ctx.setObject(obj,forKeyedSubscript:“test”)'不会。再一次,谢谢你,当我有能力时,这里是22小时内你的赏金。 – hannesr

+0

On Beta6实际上,这将是'unsafeBitCast(block,AnyObject)。“在安装Beta6时,reinterpretCast(block)as AnyObject'已被弃用,以支持'unsafeBitCast(block,AnyObject)' –

+4

。self)' –

1

我有一个工作演示在:

,这里是一个实现块的部分注册:

typealias ID = AnyObject! 
extension JSContext { 
    func fetch(key:NSString)->JSValue { 
     return getJSVinJSC(self, key) 
    } 
    func store(key:NSString, _ val:ID) { 
     setJSVinJSC(self, key, val) 
    } 
    func store(key:NSString, _ blk:()->ID) { 
     setB0JSVinJSC(self, key, blk) 
    } 
    func store(key:NSString, _ blk:(ID)->ID) { 
     setB1JSVinJSC(self, key, blk) 
    } 
    func store(key:NSString, _ blk:(ID,ID)->ID) { 
     setB2JSVinJSC(self, key, blk) 
    } 
} 

你需要一个非常小的objc代码和桥接头来使它工作。详情请参阅存储库。