phoboslab / Ejecta

A Fast, Open Source JavaScript, Canvas & Audio Implementation for iOS
2.81k stars 322 forks source link

EXC_BAD_ACCESS on scriptView invokeCallback #203

Closed guileen closed 11 years ago

guileen commented 11 years ago

Please help me on my Binding. The binding is show a UIAlertView if user click the button, then execute callback in javascript.

This is my javascript code.

var app = new Ejecta.App();
app.alert('title', 'message', 'OK', function(){
      console.log('Hello world');
});

This is my OC code.

EJ_BIND_FUNCTION(alert, ctx, argc, argv) {
    NSString *title = JSValueToNSString(ctx, argv[0]);
    NSString *message = JSValueToNSString(ctx, argv[1]);
    NSString *cancelButtonTitle = JSValueToNSString(ctx, argv[2]);
    alertCallback = JSValueToObject(ctx, argv[3], nil);

    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil];
    [alert show];
    [alert release];
    return NULL;
}

- (void) alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
    JSValueRef params[] = {};
    [scriptView invokeCallback:alertCallback thisObject:jsObject argc:0 argv:params]; // <<--- EXC_BAD_ACCESS on this line
}
finscn commented 11 years ago

I think phoboslab is falling love with Quakespasm-Rift , he doesn't love Ejecta anymore :'( . 14 days no update, 24 issues , 5 pull requests ... Tears .

switer commented 11 years ago

I think phoboslab is falling love with Quakespasm-Rift , he doesn't love Ejecta anymore :'( . 14 days no update, 24 issues , 5 pull requests ... Tears .

@finscn is falling in love with ejecta......

phoboslab commented 11 years ago

You have to protect your callback from garbage collection:

alertCallback = JSValueToObject(ctx, argv[3], nil);
JSValueProtect(ctx, alertCallback);

After you invoked the callback, you can unprotect it again:

 [scriptView invokeCallback:alertCallback thisObject:jsObject argc:0 argv:params];
JSValueUnprotect(alertCallback);