I'm creating a JSContext
and evaluating a simple piece of javascript
...
function test(obj) {
}
Next, i'm creating an NSObject
that contains nothing more then an INIT
and DEINIT
function.
When I call the javascript Test function and pass in the NSObject
, the NSObjects
DEINIT
method never gets called. I'm not sure why its not being released when nothing should be keeping it alive after the Test function executes.
Swift Playground
import UIKit
import JavaScriptCore
/**************************/
/******* SwiftObject ******/
/**************************/
@objc protocol SwiftObjectExport: JSExport {
}
class SwiftObject: NSObject, SwiftObjectExport {
override init() {
super.init()
print("[INIT] SwiftObject")
}
deinit {
print("[DEINIT] SwiftObject")
}
}
/**************************/
/******** Main ************/
/**************************/
// DEINIT does NOT fires with this test
func test() {
let jsContext = JSContext()
jsContext?.evaluateScript("function test(obj) { } ")
let obj = SwiftObject()
jsContext?.objectForKeyedSubscript("test").call(withArguments: [obj])
}
// DEINIT fires with this test
func test2() {
let jsContext = JSContext()
jsContext?.evaluateScript("function test(obj) { } ")
let obj = SwiftObject()
}
print("Running test 1...")
test() // DEINIT does NOT fires with this test
print("Running test 2...")
test2() // DEINIT fires with this test
In real application, all your code is wrapped in an autorelease pool. In playgrounds, that's not the case.
Simply add an autorelease pool around your test code, and that will fix your issue:
autoreleasepool {
print("Running test 1...")
test()
print("Running test 2...")
test2()
print("Inside autorelease pool")
}
print("Outside autorelease pool")
Output:
Running test 1...
[INIT] SwiftObject
Running test 2...
[INIT] SwiftObject
[DEINIT] SwiftObject
Inside autorelease pool
[DEINIT] SwiftObject
Outside autorelease pool