2008 06 15Crossing the WebKit bridge
UPDATE check out JSCocoa, a bridge from Javascript to Cocoa. It allows calling ObjC, C, using C structs, and definining your own classes. It's open source.
Unfortunately the WebKit bridge is not as full featured as RubyCocoa's. You can call ObjC methods, use strings, numbers and arrays, and that's it. No C methods or structs, no derivating JS objects from ObjC objects. Following Using Objective-C From JavaScript describes the possibilities, the one thing of note is that calls like [someObject someMethod:@"hello" withAnotherParam:@"world"]
are translated as someObject.someMethod_withAnotherParam_('hello', 'world')
.
What's of note
-
NSDictionary
is useless. Returning[NSDictionary dictionaryWithObjectsAndKeys:@"someString", @"key", nil]
will yield a very strange JS object. You can display it withdocument.write(hashFromObjC)
and you'll get what you expect :{ key : someString }
, but that hash is not usable at all ! Tryinghash['key']
orhash.key
gives nothing, trying to loop over it withfor (name in hash) …
gives nothing either. On the other direction, passing a hash to ObjC wil yield aWebScriptObject
, not aNSDictionary
. So, hashes are out. - Retain count. Exposing an object with
[windowScriptObject setValue:theObject forKey:@"theObject"];
retains the object. Each ObjC method returning an object retains it. If you don't 'cache' the object you got and always doobjCobjectExposedToJS.getObject().doStuff()
, the retain count of the object returned bygetObject
will be incremented each time you call it. BUT getting an object in an array doesn't retain it. - No manual garbage collection start method. Internet explorer had
GC.collect()
, useful to check for memory leaks. In Safari, there's aWebCoreStatistics
that's handling quite a lot of stuff, including garbage collection. Add a methodcollect
to your JS-exposed object that calls[objc_getClass("WebCoreStatistics") garbageCollectJavaScriptObjects]
and you'll get a manual way to start JS collection. CheckWebCoreStatistics.mm
in the WebKit source for a list of its methods, including interesting stuff likejavaScriptObjectsCount
. - Crossing stuff like
NSPoint
will have to be done with arrays.
#define NSPointToJS(p) [NSArray arrayWithObjects:[NSNumber numberWithFloat:p.x], [NSNumber numberWithFloat:p.y], nil]
#define NSPointFromJS(d) NSMakePoint([[d objectAtIndex:0] floatValue], [[d objectAtIndex:1] floatValue])
Does passing arrays from JS to ObjC work for you? If I try it, I get a WebScriptObject instead of an NSArray (even though the docs say it's supposed to work).