मैंने NSManagedObjectContext और बहु-थ्रेडेड अनुप्रयोगों के बारे में यहां कई पोस्ट पढ़ी हैं। मैं CoreDataBooks उदाहरण पर भी गया हूं यह समझने के लिए कि अलग-अलग धागे को अपने स्वयं के एनएसएमएनेज्ड ऑब्जेक्ट कॉन्टेक्स्ट की आवश्यकता होती है, और मुख्य एनएसएएनएजेडऑब्जेक्ट कॉन्टेक्स्ट के साथ एक सेव ऑपरेशन कैसे विलय हो जाता है। मुझे अच्छा होने का उदाहरण मिला, लेकिन यह भी आवेदन विशिष्ट है। मैं इसे सामान्य बनाने की कोशिश कर रहा हूं, और आश्चर्यचकित हूं कि मेरा दृष्टिकोण अच्छा है या नहीं।बहु-थ्रेडेड अनुप्रयोग में NSManagedObjectContext के जेनेरिक दृष्टिकोण
मेरा दृष्टिकोण वर्तमान धागे के लिए NSManagedObjectContext लाने के लिए एक सामान्य कार्य होना है। फ़ंक्शन मुख्य थ्रेड के लिए NSManagedObjectContext देता है, लेकिन एक अलग थ्रेड के भीतर से बुलाए जाने पर एक नया (या इसे कैश से लाया जाएगा) बना देगा। यह निम्नानुसार है:
+(NSManagedObjectContext *)managedObjectContext {
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *moc = delegate.managedObjectContext;
NSThread *thread = [NSThread currentThread];
if ([thread isMainThread]) {
return moc;
}
// a key to cache the context for the given thread
NSString *threadKey = [NSString stringWithFormat:@"%p", thread];
// delegate.managedObjectContexts is a mutable dictionary in the app delegate
NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts;
if ([managedObjectContexts objectForKey:threadKey] == nil) {
// create a context for this thread
NSManagedObjectContext *threadContext = [[[NSManagedObjectContext alloc] init] autorelease];
[threadContext setPersistentStoreCoordinator:[moc persistentStoreCoordinator]];
// cache the context for this thread
[managedObjectContexts setObject:threadContext forKey:threadKey];
}
return [managedObjectContexts objectForKey:threadKey];
}
मुख्य धागे से बुलाए जाने पर सहेजें ऑपरेशन सरल होते हैं। अन्य धागे से बुलाए गए ऑपरेशंस को मुख्य थ्रेड के भीतर विलय की आवश्यकता होती है।
+(void)commit {
// get the moc for this thread
NSManagedObjectContext *moc = [self managedObjectContext];
NSThread *thread = [NSThread currentThread];
if ([thread isMainThread] == NO) {
// only observe notifications other than the main thread
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:moc];
}
NSError *error;
if (![moc save:&error]) {
// fail
}
if ([thread isMainThread] == NO) {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:moc];
}
}
contextDidSave:
समारोह हम मर्ज, अगर commit
में अधिसूचना द्वारा कहा जाता है: कि के लिए मैं एक सामान्य commit
समारोह है।
+(void)contextDidSave:(NSNotification*)saveNotification {
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *moc = delegate.managedObjectContext;
[moc performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:saveNotification
waitUntilDone:YES];
}
अंत में, हम साफ-अप NSManagedObjectContext का कैश इस के साथ:
+(void)initialize {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(threadExit)
name:NSThreadWillExitNotification
object:nil];
}
+(void)threadExit {
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *threadKey = [NSString stringWithFormat:@"%p", [NSThread currentThread]];
NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts;
[managedObjectContexts removeObjectForKey:threadKey];
}
यह संकलित करता है तथा काम करने के लिए लगता है, लेकिन मैं समस्याओं सूत्रण दौड़ की स्थिति के कारण मुश्किल हो सकता है पता है। क्या किसी को इस दृष्टिकोण के साथ कोई समस्या दिखाई देती है?
इसके अलावा, मैं इसे एसिंक्रोनस अनुरोध (ASIHTTPRequest का उपयोग करके) के संदर्भ में उपयोग कर रहा हूं, जो सर्वर से कुछ डेटा प्राप्त करता है और अपडेट करता है और आईफोन पर स्टोर को सम्मिलित करता है। ऐसा लगता है कि अनुरोध पूरा होने के बाद NSThreadWillExitNotification आग नहीं आता है, और उसके बाद उसी अनुरोध को बाद के अनुरोधों के लिए उपयोग किया जाता है। इसका मतलब है कि एक ही थ्रेड पर अलग-अलग अनुरोधों के लिए एक ही NSManagedObjectContext का उपयोग किया जाता है। क्या ये एक दिक्कत है?
क्रिस, एनएस ऑपरेशन कतार में सभी परिचालनों के लिए मुख्य धागे में बनाए गए एक एकल एनएसएमएनेज्ड ऑब्जेक्ट कॉन्टेक्स्ट का उपयोग करते समय मुझे एक समान बहु थ्रेडिंग समस्या का सामना करना पड़ रहा है। Probkem आता है जब प्रत्येक धागा संदर्भ को बचाने की कोशिश करता है, ऐप यादृच्छिक रूप से कोर डेटा से अपवाद फेंकता है। मैं सभी परिचालनों में उपयोग करते समय इस संदर्भ को लॉक करने के बारे में सोच रहा था, ताकि उनमें से प्रत्येक को संदर्भ का एक विशेष उपयोग होगा। मैंने उपरोक्त समाधान को पढ़ा है। गड़बड़ियां, कृपया मुझे नया कोड चिपकाएं जिसे आपने संदर्भ विलय करने के लिए उपयोग किया है और कृपया प्लेइन –