嵌套完成处理程序中的Swift JSValue callWithArguments()导致BAD_ACCESS

时间:2015-10-22 19:39:12

标签: swift

我有一个简单的函数,它将完成处理程序作为JSValue。它是一个JSValue,因为我使用这个函数作为JSExport协议的一部分。

然后,此函数使用另一个完成处理程序调用另一个内部方法。当调用第二个处理程序时,我想在JSValue上调用WithArguments。

当我从第二个完成处理程序外部调用WithAnguments时,这一切都按预期工作,但是从第二个处理程序调用时我得到一个BAD_ACCESS。

func myFunction(completion: JSValue) {

    // If I put completion.callWithAttributes([]) here, everything works fine.

    self.mySecondFunction(completion: {(result: Dictionary<String, AnyObject>) -> Void in

        // If I put completion.callWithAttributes([]) here, I get a BAD_ACCESS
    })
}

任何帮助非常感谢。谢谢!

1 个答案:

答案 0 :(得分:0)

我强烈建议您执行以下操作

[self.callback.context[@"setTimeout"]  
             callWithArguments:@[callback, @0, items]];  

当您要向JavaScriptCore对应方发送响应时。这将阻止TVML UI MainThread挂起。正如您所看到的那样,调用setTimeout javascript函数时延迟为0,您的回调和项目作为参数如下:

setTimeout(callback,0,items) 

我不知道你是怎么创建警报的,不管怎么说这是Apple的一个:

createAlert : function(title, description) {  
  var alertString = `<?xml version="1.0" encoding="UTF-8" ?>  
  <document>  
  <alertTemplate>  
  <title>${title}</title>  
  <description>${description}</description>  
  <button class="btn_close">  
  <text>OK</text>  
  </button>  
  </alertTemplate>  
  </document>`  
  var parser = new DOMParser();  
  var alertDoc = parser.parseFromString(alertString, "application/xml");  
  return alertDoc  
  }  

与警报和您在此处看到的行为没有直接关系,这更像是调用此事件的副作用

completion.callWithArguments([]) 

以一种意想不到的方式。最好在某处保存完成,并在对象实例上获取它的引用。然后,当长任务结束时,你调用它。此外,如果你执行一项长期任务,那么你在NSOperation中移动所有内容是合理的:

/** JavaScriptCore Callback Operation */  
@interface JSCallbackOperation: NSOperation  
@property(nonatomic, strong) JSValue*callback;  
@property(nonatomic, strong) id items;  
@end  
@implementation JSCallbackOperation  
- (id)initWithItems:(id)items callback:(JSValue*)callback {  
    if(self = [super init]) {  
        self.items=items;  
        self.callback=callback;  
    }  
    return self;  
}  
- (void)main {  
    @autoreleasepool {  
        if(self.callback) {  
            NSLog(@"Dispatching %@", self.callback);  
            [self.callback.context[@"setTimeout"]  
             callWithArguments:@[self.callback, @0, self.items]];  
        }  
    }  
}  

此时你定义一个帮助器,用参数调用回调:

#pragma mark - API Helper  
- (void)handleResponseWithItems:(id)items callback:(JSValue*)callback {  

    NSArray *active_and_pending_operations = operationQueue.operations;  
    NSInteger count_of_operations = operationQueue.operationCount;  

    NSLog(@"Running operations: %ld of %ld", active_and_pending_operations.count, count_of_operations);  

    JSCallbackOperation *op = [[JSCallbackOperation alloc] initWithItems:items callback:callback];  
    [op setQueuePriority:NSOperationQueuePriorityNormal];  
    [op setCompletionBlock:^{  
        NSLog(@"Operation completed.");  
    }];  
    [operationQueue addOperation:op];  

}