मैं JSManagedValue का उपयोग करने का प्रयास करते समय समस्याओं में भाग रहा हूं। Session 615 at WWDC 2013 पर आधारित मेरी समझ से, जब आप ऑब्जेक्टिव-सी से जावास्क्रिप्ट में संदर्भ लेना चाहते हैं और इसके विपरीत, आपको संदर्भ चक्र से बचने के लिए उद्देश्य-सी में JSValue को संग्रहीत करने के बजाय JSManagedValue का उपयोग करना होगा।JSValue जारी किए बिना संदर्भ चक्र से बचने के लिए मैं JSManagedValue का उपयोग कैसे कर सकता हूं?
मैं जो करने का प्रयास कर रहा हूं उसका एक अलग-अलग संस्करण यहां दिया गया है। मेरे पास एक व्यू कंट्रोलर है जिसे जावास्क्रिप्ट ऑब्जेक्ट के संदर्भ की आवश्यकता है, और जावास्क्रिप्ट ऑब्जेक्ट को ViewController पर एक विधि कॉल करने में सक्षम होना चाहिए। व्यू कंट्रोलर में एक यूआईएलएबल है जो एक गिनती प्रदर्शित करता है, और इसमें दो UIButtons हैं, 'जोड़ें' जो गिनती को बढ़ाता है, और 'रीसेट' करता है, जो वर्तमान व्यू कंट्रोलर को एक नए व्यू कंट्रोलर के साथ बनाता है और बदल देता है (मूल रूप से बस मैं पुराने व्यू कंट्रोलर को सत्यापित कर सकता हूं जब मैं इसका परीक्षण कर रहा हूं, ठीक से साफ हो जाता है)।
viewDidLoad
में, व्यू कंट्रोलर updateLabel
पर कॉल करता है और जावास्क्रिप्ट ऑब्जेक्ट से गिनती को सही ढंग से प्राप्त करने में सक्षम है। हालांकि, उस रन लूप खत्म होने के बाद, इंस्ट्रूमेंट्स दिखा रहा है कि JSValue जारी हो रहा है। ViewController अभी भी मौजूद है, जैसा कि इसके JSManagedValue करता है, इसलिए मैंने सोचा कि JSValue को कचरा होने से रोकना चाहिए, लेकिन _managedValue.value
अब शून्य लौटाता है।
यदि मैं JSManagedValue का उपयोग करने के बजाय JSValue को संग्रहीत करता हूं, तो यह सभी दृश्यमान रूप से काम करता है, लेकिन व्यू कंट्रोलर और जेएसवेल्यू के बीच एक संदर्भ चक्र है, जैसा कि अपेक्षित है, और इंस्ट्रूमेंट्स पुष्टि करता है कि व्यू कंट्रोलर कभी जारी नहीं किए जाते हैं।
जावास्क्रिप्ट कोड:
(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;
}
क्या है इस सेटअप को संभालने का सही तरीका ताकि JSValue को ViewController के पूरे जीवनकाल में बरकरार रखा जा सके लेकिन कोई संदर्भ चक्र नहीं बनाया गया है ताकि ViewController को साफ़ किया जा सके?
मुझे लगता है कि यह सही है। मुझे यह पुष्टि करने के लिए सत्र 615 के लिए वीडियो से स्रोत कोड को पढ़ने के लिए मजबूर होना पड़ता है हालांकि: नमूना प्रोजेक्ट अभी भी उपलब्ध होने पर यह अच्छा होगा। – Poulsbo
नमूना कोड वर्तमान में यहां है: https://developer.apple.com/downloads/index.action?name=WWDC%202013 – Poulsbo