[View]  [Edit]  [Lock]  [References]  [Attachments]  [History]  [Home]  [Changes]  [Search]  [Help] 

[coco8] How to implement NSArray enumeration

The technique requires the following steps of resolution
  1. implement a (native) method in JSC to return a block with required signature/type
  2. instantiate the (objetiveC) block, in runtime and pass the block as argument to the native call

How to write the block instantiation method?

Edit the JSCocoaController class adding a method to get the block
#pragma mark blocks
- (id)enumerationBlockCalling: (JSValueRefAndContextRef)callbackFunction
{
    JSContextRef mainContext = [[JSCocoa controllerFromContext:callbackFunction.ctx] ctx];
    JSValueProtect(mainContext, callbackFunction.value);
    [JSCocoaController upJSValueProtectCount];

    void (^aBlock)(id,NSUInteger,BOOL* ) = ^(id obj, NSUInteger idx, BOOL* stop) {
        id jsc = [JSCocoa controllerFromContext:mainContext];
        JSObjectRef fn = JSValueToObject(mainContext, callbackFunction.value, NULL);
        id args = [NSArray arrayWithObjects:obj
                   ,[NSNumber numberWithInteger:idx]
                   , nil];
        JSValueRef res = [ jsc callJSFunction:fn withArguments:args ];
        *stop = JSValueToBoolean(mainContext, res);
    };
    
    return [aBlock copy];
}

How to make the call, and pass the block argument from S8 side?

Use the method implemented in JSCocoaController to instantiate the block, and pass a S8 block to be evaluated when evaluating the ObjectiveC block from native side.
| anArray string walked |
	anArray := NSArray @ #( #A #B #C #M ).
	string := #c.
	walked := #().
	anArray enumerateObjectsUsingBlock: (S8BlockAdaptor instance enumerationBlockCalling: [:obj :index|
		walked add: obj.
		obj asLowercase = string asLowercase "found"
	]).
	^walked printString