gpt4 book ai didi

javascript - 在没有释放 JSValue 的情况下,如何使用 JSManagedValue 来避免引用循环?

转载 作者:太空狗 更新时间:2023-10-30 03:54:03 24 4
gpt4 key购买 nike

我在尝试使用 JSManagedValue 时遇到问题。根据我的理解 Session 615 at WWDC 2013 ,当您想要从 Objective-C 引用 Javascript 时,反之亦然,您需要使用 JSManagedValue 而不是仅将 JSValue 存储在 Objective-C 中以避免引用循环。

这是我正在尝试做的事情的精简版。我有一个需要引用 Javascript 对象的 ViewController,并且该 Javascript 对象需要能够调用 ViewController 上的方法。 ViewController 有一个显示计数的 UILabel,还有两个 UIButton,一个是增加计数的“Add”,另一个是“Reset”,它创建并用一个新的 ViewController 替换当前的 View Controller (基本上只是为了验证旧的 ViewController在我测试这个时得到正确清理)。

viewDidLoad 中,ViewController 调用 updateLabel 并能够从 Javascript 对象中正确获取计数。然而,在该运行循环完成后,Instruments 显示 JSValue 正在被释放。 ViewController 和它的 JSManagedValue 仍然存在,所以我认为这应该可以防止 JSValue 被垃圾收集,但是 _managedValue.value 现在返回 nil。

如果我只是存储 JSValue 而不是使用 JSManagedValue,这一切都在视觉上有效,但 ViewController 和 JSValue 之间存在引用循环,正如预期的那样,并且 Instruments 确认 ViewController 从未被释放。

Javascript 代码:

(function() {
var _count = 1;
var _view;
return {
add: function() {
_count++;
_view.updateLabel();
},
count: function() {
return _count;
},
setView: function(view) {
_view = view;
}
};
})()

CAViewController.h

@protocol CAViewExports <JSExport>
- (void)updateLabel;
@end

@interface CAViewController : UIViewController<CAViewExports>
@property (nonatomic, weak) IBOutlet UILabel *countLabel;
@end

CAViewController.m

@interface CAViewController () {
JSManagedValue *_managedValue;
}
@end

@implementation CAViewController

- (id)init {
if (self = [super init]) {
JSContext *context = [[JSContext alloc] init];

JSValue *value = [context evaluateScript:@"...JS Code Shown Above..."];
[value[@"setView"] callWithArguments:@[self]];

_managedValue = [JSManagedValue managedValueWithValue:value];
[context.virtualMachine addManagedReference:_managedValue withOwner:self];
}
return self;
}

- (void)viewDidLoad {
[self updateLabel];
}

- (void)updateLabel {
JSValue *countFunc = _managedValue.value[@"count"];
JSValue *count = [countFunc callWithArguments:@[]];
self.countLabel.text = [count toString];
}

- (IBAction)add:(id)sender {
JSValue *addFunc = _managedValue.value[@"add"];
[addFunc callWithArguments:@[]];
}

- (IBAction)reset:(id)sender {
UIApplication *app = [UIApplication sharedApplication];
CAAppDelegate *appDelegate = app.delegate;
CAViewController *vc = [[CAViewController alloc] init];
appDelegate.window.rootViewController = vc;
}

处理此设置的正确方法是什么,以便在 ViewController 的整个生命周期中保留 JSValue,但不创建引用循环,以便可以清理 ViewController?

最佳答案

我也被这个弄糊涂了。在阅读了 JavaScriptCore header 以及 ColorMyWords 示例项目之后,似乎要使托管值保持其值有效,所有者必须对 JavaScript 可见(即,分配给上下文中的值)。您可以在 ColorMyWords 项目的 AppDelegate.m 的 -loadColorsPlugin 方法中看到这一点。

关于javascript - 在没有释放 JSValue 的情况下,如何使用 JSManagedValue 来避免引用循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19202248/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com