2014-07-06 117 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代碼和橋接頭來使它工作。詳情請參閱存儲庫。