ObjectiveC e JavaScriptCore: O uso desse método de chamada de CallBacks causará problemas de memória?
AVISO LEGAL: Este é um post longo, mas pode ser muito valioso para aqueles que tentam usar o novo framework ObjectiveC JavascriptCore e fazer codificação assíncrona entre ObjC e JS.
Olá, sou super novo no Objective C e estou integrando uma biblioteca de comunicação javascript no meu aplicativo iOS.
De qualquer forma, estou tentando usar o novo ObjectiveC JavaScriptCore Framework introduzido no iOS7. É bastante impressionante na maioria das vezes, apesar de pouco documentado até agora.
É realmente estranho convenções de linguagem de mistura, mas também meio libertador de algumas maneiras.
Devo acrescentar que, é claro, estou usando o ARC, o que ajuda muito vindo do mundo Javascript. Mas eu tenho uma pergunta bastante específica sobre problemas de uso de memória ao mover entre o ObjectiveC e os callBacks do JSContext. Por exemplo, se eu executar uma função em Javascript que, em seguida, executa algum código assíncrono e, em seguida, chama de volta para um bloco ObjectiveC definido, e então chama um retorno de chamada JS definido ... Eu só quero ter certeza de que estou fazendo o certo (por exemplo, (não vazando memória em algum lugar)!
Apenas para fazer as coisas apropriadamente (porque eu faço referência à classeself
para chamar os callBacks da ObjectiveC, crio umweakSelf
portanto, ele funciona bem com o ARC (referenciado na pergunta:capturar-se fortemente neste bloco provavelmente levará a um ciclo de retenção):
__unsafe_unretained typeof(self) weakSelf = self;
Agora, diga que eu tenho umJSContext
e adicione uma função a ele. Eu quero que esta função pegue uma função callBack e chame-a com "Hello" como argumentobem como passar OUTRA função, como callBack. ie
// Add a new JSContext.
JSContext context = [[JSContext alloc] initWithVirtualMachine:[[JSVirtualMachine alloc] init]];
// Add a function to the context. This function takes a callBack function and calls it back with "Hello"
[context evaluateScript: @"var functionA = function(callBack){
var aMessage = "Foo";
callBack(aMessage, function(message){
/* message should say: Foo Bar */
});
}" ];
// Note, if you try to copy this code, you will have to get rid of the returns in the JS script.
Ok, então temos nosso lado JS básico. Agora, para adicionar a complexidade do ObjectiveC. Vou adicionar o primeiro bloco do ObjectiveC CallBack:
context[@"functionB"] = ^(NSString *theMessage, JSValue *theCallBack){
[weakSelf objCFunction:theMessage withCallBack:theCallBack];
};
Na mesma classe, tudo isso está acontecendo. Também tenho a definição do método.Este é o lugar que mais me preocupa:
-(void)objCFunction:(NSString *)message withCallBack:(JSValue *)callBack
{
NSString *concatenatedString = [NSString stringWithFormat:@"%@%@", message, @"Bar"];
[callBack callWithArguments:@[concatenatedString]];
}
Então, quando eu ligo:
[context evaluateScript: @"functionA(functionB);" ];
Deve passar pela cadeia e faz exatamente o que eu espero que faça.
Minha principal preocupação é que espero não estar de alguma forma capturando um JSValue em algum lugar dessa cadeia que esteja vazando.
Qualquer ajuda para me ajudar a entender como o ARC / JSMachine gerenciaria essa abordagem para chamar callBacks fluidamente entre o Objetivo C e o Javascript seria muito valioso!
Além disso, espero que essa pergunta ajude outras pessoas que estão experimentando essa estrutura.
Obrigado!