Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions 2015-01-19-javascriptcore.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ NSLog(@"Tripled: %d", [tripleNum toInt32]);
We can easily access any values we've created in our `context` using subscript notation on both `JSContext` and `JSValue` instances. `JSContext` requires a string subscript, while `JSValue` allows either string or integer subscripts for delving down into objects and arrays:

````swift
let names = context.objectForKeyedSubscript("names")
let names = context.objectForKeyedSubscript("names" as NSString)
let initialName = names?.objectAtIndexedSubscript(0)
print("The first name: \(initialName?.toString() ?? "none")")
// The first name: Grace
Expand Down Expand Up @@ -154,6 +154,28 @@ NSLog(@"%@", [context evaluateScript:@"simplifyString('안녕하세요!')"]);

> There's another speedbump for Swift here—note that this only works for *Objective-C blocks*, not Swift closures. To use a Swift closure in a `JSContext`, declare it with the `@convention(block)` attribute.

> We also have to use `NSString` as the key value for `forKeyedSubscript:`. It makes our key lookups even more verbose in Swift than the neat subscript syntaxt we have in Objective-C.

> We can make this less painful (with an extension)[https://gist.github.com/jasonm23/53b49dddbd07fa9aafd9a07b6eed6693] to give `JSContext` subscript access to objects via `String` keys.

````swift
extension JSContext {
subscript(_ get: String) -> JSValue! {
get {
return self.objectForKeyedSubscript(get)
}
set { fatalError("get: cannot be used to set") }
}

subscript(_ set: String) -> Any! {
set {
self.setObject(newValue, forKeyedSubscript: set as NSString)
}
get { fatalError("set: cannot be used to get") }
}
}
````

#### Memory Management

Since blocks can capture references to variables and `JSContext`s maintain strong references to all their variables, some care needs to be taken to avoid strong reference cycles. Avoid capturing your `JSContext` or any `JSValue`s inside a block. Instead, use `[JSContext currentContext]` to get the current context and pass any values you need as parameters.
Expand Down Expand Up @@ -250,7 +272,7 @@ Before we can use the `Person` class we've created, we need to export it to the

````swift
// export Person class
context.setObject(Person.self, forKeyedSubscript: "Person")
context.setObject(Person.self, forKeyedSubscript: "Person" as NSString)

// load Mustache.js
if let mustacheJSString = String(contentsOfFile:..., encoding:NSUTF8StringEncoding, error:nil) {
Expand Down