문제

I have two JSContexts, and I want to swap JSValues between them from time to time. However, I'm having difficulty moving a JSValue to a new context, if that's possible.

I'm trying this:

newContext[@"newValue"] = [JSValue valueWithObject:newValue inContext:newContext];

While the new context now has that value, the value still retains its old context. Unfortunately, it still retains its old context. Any suggestions?

도움이 되었습니까?

해결책

I suggest you extract the value of the JSValue from its old javascript context into an ordinary objective-c object before creating the new JSValue in the new context. Looking at JSValue.h shows that the JSValue class has a read-only property that holds the JSContext that the value originates from.

I can't tell what type of value you are dealing with from your code above, but for example (for simple types):

NSString *newString = [newValue toString]; // Extract from old JSValue
newContext[@"newValue"] = newString;

or for a more complex object:

@protocol MyPointExports <JSExport>
@property double x;
@property double y;
@end

@interface MyPoint : NSObject <MyPointExports>
// Put methods and properties not visible to JavaScript code here.
@end

newcontext[@"MyPoint"] = [MyPoint class]; // Define the class in Javascript

...

MyPoint *p = [newValue toObject]; // Extract from old JSValue
newContext[@"newValue"] = p;

Note that the value will still exist in the old JSContext (the old JSContext will remain alive whilst the old value is retained). You may want to remove this reference by:

oldContext[@"oldValue"] = nil; // Assuming the var in the oldContext was called oldValue

Note also that you don't need to use the constructor:

+ (JSValue *)valueWithObject:(id)value inContext:(JSContext *)context;

since JavaScriptCore has built-in conversion for the following (see JSValue.h):

  Objective-C type  |   JavaScript type
--------------------+---------------------
        nil         |     undefined
       NSNull       |        null
      NSString      |       string
      NSNumber      |   number, boolean
    NSDictionary    |   Object object
      NSArray       |    Array object
       NSDate       |     Date object
      NSBlock *     |   Function object *
         id **      |   Wrapper object **
       Class ***    | Constructor object ***

* Instances of NSBlock with supported arguments types will be presented to
JavaScript as a callable Function object. For more information on supported
argument types see JSExport.h. If a JavaScript Function originating from an
Objective-C block is converted back to an Objective-C object the block will
be returned. All other JavaScript functions will be converted in the same
manner as a JavaScript object of type Object.

** For Objective-C instances that do not derive from the set of types listed
above, a wrapper object to provide a retaining handle to the Objective-C
instance from JavaScript. For more information on these wrapper objects, see
JSExport.h. When a JavaScript wrapper object is converted back to Objective-C
the Objective-C instance being retained by the wrapper is returned.

*** For Objective-C Class objects a constructor object containing exported
class methods will be returned. See JSExport.h for more information on
constructor objects.

다른 팁

Actually, you don't need to worry about context in JSValue, if you put a breakpoint in javascript code, you can see the object passed from Native doesn't have a context property. The context in JSValue is only for showing the original JSContext and doesn't really link to it.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top