2016-06-19 14 views
5

Tôi đang viết Ứng dụng iOS (sử dụng xcode 7.3 và nhanh 2.2) bằng cách sử dụng khung JavascriptCode. Gọi javascript phương pháp từ các công trình nhanh chóng hoàn hảo, nhưng khi tôi gọi phương thức nhanh chóng từ javascript, xcode chỉ đơn giản là cho thấy một "tải" loại biểu tượng và không có gì xảy ra. Tôi cần phải "buộc bỏ" xcode để thoát khỏi trạng thái này. Tôi đã theo dõi https://www.raywenderlich.com/124075/javascriptcore-tutorialhttp://nshipster.com/javascriptcore/ và tôi đang thử các cuộc gọi khá đơn giản.Gọi đến phương thức nhanh từ JavaScript treo xcode và ứng dụng

Có ai phải đối mặt với loại sự cố này không?

đang nhanh chóng của tôi là như sau:

@objc protocol WindowJSExports : JSExport { 
    var name: String { get set } 
    func getName() -> String 
    static func createWindowWithName(name: String) -> WindowJS 
} 

@objc class WindowJS : NSObject, WindowJSExports { 
    dynamic var name: String 
    init(name: String) { 
     self.name = name 
    }  
    class func createWindowWithName(name: String) -> WindowJS { 
     return WindowJS(name: name) 
    }  
    func getName() -> String { 
     NSLog("getName called from JS context") 
     return "\(name)" 
    } 
} 

Tôi khởi tạo bối cảnh như sau:

runContext = JSContext() 
runContext.name = "test_Context" 

windowToJs = WindowJS(name: "test") 
runContext.setObject(windowToJs.self, forKeyedSubscript: "WindowJS") 

Nếu tôi thay thế hai dòng cuối cùng trong mã trên với dưới mã mà không instantiating nó, mã không tải được.

runContext.setObject(WindowJS.self, forKeyedSubscript: "WindowJS") 

Và mã javascript đơn giản như

function check() { 
    return WindowJS.getName() 
} 

Tôi thấy breakpoint bị trúng trong việc kiểm tra chức năng JS và khi WindowJS.getName được gọi, xcode đơn giản trở nên bất tỉnh.

+0

Cuộc gọi JavaScript được kích hoạt như thế nào? Liệu nó có phải là ngẫu nhiên được kích hoạt bằng cách gọi nó (thậm chí là một tác dụng phụ) từ Swift không? Ví dụ: bạn có thể kết thúc bằng Swift-> JS-> Swift cycle không? – DarkDust

+0

@DarkDust Cảm ơn! Đó là những gì đang xảy ra. Làm thế nào tôi có thể đạt được một hiệu ứng không đồng bộ như của "postMessage trong JavaScript trong WKWebView" trong một JSContext? – Amruta

Trả lời

2

Bạn đang tạo bế tắc vì bạn đang gọi từ Swift sang JavaScript trở lại Swift. Tôi không chắc chắn lý do tại sao nó là một bế tắc nhưng tôi đã có một vấn đề tương tự với WKWebView trên Mac gần đây.

Bạn cần tách riêng điều này và làm cho giao tiếp không đồng bộ. Điều này rõ ràng có nghĩa là bạn không thể đơn giản trả về một giá trị từ hàm JS của bạn trong trường hợp này.

Để phân tách, bạn có thể phá vỡ thế bế tắc bằng cách trì hoãn công việc hàm JavaScript cần phải làm ra khỏi runloop hiện lặp đi lặp lại sử dụng setTimeout:

function myFunction() { 
    setTimeout(function() { 
    // The actual work is done here. 
    // Call the Swift part here. 
    }, 0); 
} 

Toàn bộ bản địa ↔︎ truyền JavaScript là rất, rất khó khăn . Tránh nó nếu bạn có thể. Có một dự án được gọi là XWebView có thể giúp bạn vì nó cố gắng làm dịu cầu nối giữa hai thế giới.

+0

Cảm ơn! Tôi gặp lỗi cho setTimeout. Bạn có cần phải làm bất cứ điều gì đặc biệt cho setTimeout (/ * someCode * /, 0) để làm việc không? Tôi cũng cần điều đó. – Amruta

+0

Bạn cần truyền chức năng này. Tìm kiếm trên web, có rất nhiều ví dụ về cách sử dụng nó. – DarkDust

1

SetTimeout có thể được giải quyết bằng cách thêm đoạn mã sau vào hàm nhanh của tôi.

let setTimeout: @convention(block) (JSValue, Int) ->() = 
{ callback, timeout in 
    let timeVal = Int64(timeout) 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeVal), dispatch_get_main_queue(), { callback.callWithArguments(nil)}) 
} 

Để hiển thị mã gốc này cho bối cảnh JS, tôi cũng thêm vào sau.

runContext.setObject(unsafeBitCast(setTimeout, AnyObject.self), forKeyedSubscript: "setTimeout") 

Mọi thứ sau đó hoạt động tốt.

Các vấn đề liên quan