2014-07-25 7 views
6

देता है मैं एक अलग संदर्भ से एकत्रित ऑब्जेक्ट आईडी की सरणी का उपयोग करके संदर्भ से प्रबंधित ऑब्जेक्ट पुनर्प्राप्त करने के लिए एक fetch निष्पादित करने का प्रयास कर रहा हूं। हालांकि, fetch एक खाली सरणी के साथ वापस आता है।ऑब्जेक्ट आईडी द्वारा NSManagedObjects की सरणी प्राप्त करना खाली सरणी

"कोर डाटा प्रोग्रामिंग गाइड" link की "विशिष्ट वस्तुओं प्राप्त कर रहा है" खंड से

:

आपके आवेदन कई संदर्भों का उपयोग करता है और आप परीक्षण करने के लिए है कि क्या एक वस्तु एक लगातार की दुकान से हटा दिया गया है चाहते हैं , आप फॉर्म स्वयं ==% @ के अनुमान के साथ एक fetch अनुरोध बना सकते हैं। जिस वस्तु को आप चर के रूप में पास करते हैं वह या तो एक प्रबंधित ऑब्जेक्ट या प्रबंधित ऑब्जेक्ट आईडी हो सकता है ... "

यदि आपको कई ऑब्जेक्ट्स के अस्तित्व के लिए परीक्षण करने की आवश्यकता है, तो यह IN ऑपरेटर का उपयोग करने के लिए अधिक कुशल है

NSPredicate * विधेय =: कई फ़ेच उदाहरण के लिए, अलग-अलग वस्तुओं के लिए निष्पादित करने के लिए है [NSPredicate predicateWithFormat: @ "% @ में स्व", arrayOfManagedObjectIDs];

हालांकि इस वस्तु के लिए परीक्षण के बारे में बात कर रही है हटाना, मुझे लगता है कि ऑब्जेक्ट्स हटाए नहीं गए हैं तो परिणाम सरणी खाली नहीं है, और इसमें शामिल होगा वास्तविक एनएसएएनएजेड ऑब्जेक्ट्स। हालांकि, जब मैं इस कोड को निष्पादित करें:

- (NSArray *)managedObjectsOfEntityName:(NSString *)entityName fromObjectIDs:(NSArray *)objectIDs managedObjectContext:(NSManagedObjectContext *)managedObjectContext 
{ 
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName]; 
    request.predicate = [NSPredicate predicateWithFormat:@"self IN %@", objectIDs]; 

    __autoreleasing NSError *error = nil; 

    NSManagedObjectID *testID = objectIDs[0]; 
    NSManagedObject *obj = [managedObjectContext existingObjectWithID:testID error:&error]; 
    if (!obj) 
    { 
     NSLog(@"Unable to perform fetch. Error: %@", error); 
    } 

    error = nil; 
    NSArray *results = [managedObjectContext executeFetchRequest:request error:&error]; 
    if (!results) 
    { 
     NSLog(@"Unable to perform fetch. Error: %@", error); 
    } 

    return results; 
} 

results सरणी, गैर शून्य और खाली है, जबकि obj ठीक से भर जाता है।

मैंने स्वच्छता जांच के रूप में existingObjectWithID: पर स्पष्ट कॉल जोड़ा है, और यह बिना किसी त्रुटि के अपेक्षित ऑब्जेक्ट के साथ आता है।

यहाँ प्रासंगिक चर के लिए डिबगर उत्पादन है:

(lldb) po entityName 
Foo 

(lldb) po objectIDs 
<__NSArrayI 0x1170d4950>(
0xd0000000055c0082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p343>, 
0xd000000008e80082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p570>, 
0xd000000008840082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p545>, 
0xd000000006040082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p385>, 
0xd000000007740082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p477>, 
0xd000000008280082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p522>, 
0xd000000008e40082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p569> 
) 

(lldb) po request 
<NSFetchRequest: 0x10f338840> (entity: Foo; predicate: (SELF IN { 
0xd0000000055c0082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p343>, 
0xd000000008e80082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p570>, 
0xd000000008840082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p545>, 
0xd000000006040082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p385>, 
0xd000000007740082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p477>, 
0xd000000008280082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p522>, 
0xd000000008e40082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p569>}); 
sortDescriptors: ((null)); type: NSManagedObjectResultType;) 

(lldb) po request.predicate 
SELF IN { 
0xd0000000055c0082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p343>, 
0xd000000008e80082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p570>, 
0xd000000008840082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p545>, 
0xd000000006040082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p385>, 
0xd000000007740082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p477>, 
0xd000000008280082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p522>, 
0xd000000008e40082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p569>} 

(lldb) po testID 
0xd0000000055c0082 <x-coredata://CEB1EDA5-7F7A-4342-85E5-6C2E261308CC/Foo/p343> 

(lldb) p testID.isTemporaryID 
(bool) $7 = false 

(lldb) p obj 
(NSManagedObject *) $9 = 0x000000010f338630 

(lldb) po results 
<__NSArrayI 0x10f205c70>(

) 

(lldb) po testID.entity 
nil 

testID पर nilentity अजीब है, लेकिन मुझे यकीन है कि नहीं कर रहा हूँ "बुरा।"

तो, मुझे स्पष्ट रूप से नुकसान हुआ है कि क्यों fetch खाली वापस आ रहा है। इकाई का नाम सही है, लाने और भविष्यवाणी अच्छी लगती है, और वस्तु संदर्भ में है, लेकिन फिर भी शून्य परिणाम।

अतिरिक्त प्रसंग:

अनिवार्य रूप से, बड़ी तस्वीर है कि मैं जो कुछ काम करने के लिए अपने स्वयं के प्रबंधित ऑब्जेक्ट संदर्भ (एमओसी) का उपयोग करता है एक पृष्ठभूमि आपरेशन है। मुख्य कतार पर उस काम के परिणाम की आवश्यकता होती है, इसलिए मैं काम से उत्पन्न ऑब्जेक्ट आईडी को पैकेज करता हूं और उन्हें मुख्य कतार में भेजता हूं। मुख्य कतार पर मुझे वास्तविक प्रबंधित वस्तुओं की आवश्यकता है, इसलिए मैं मुख्य कतार के एमओसी से ऑब्जेक्ट आईडी द्वारा उन्हें लाने की कोशिश कर रहा हूं। मुझे लगता है मैं इन वस्तुओं को पाने के लिए एमओसी पर objectWithID: या existingObjectWithID:error: या यहाँ तक कि objectRegisteredForID: उपयोग कर सकते हैं, लेकिन प्रत्येक अपने स्वयं के विशेष मुद्दे हैं:

  • objectWithID: एक वस्तु जो फर्जी है अगर वस्तु के संदर्भ में नहीं है वापस कर सकती है, और यदि यह संदर्भ में है तो यह एक गलती वापस कर देगा।
  • existingObjectWithID:error: बहुत अच्छा है, क्योंकि हम nil (एक फर्जी ऑब्जेक्ट के बजाए) वापस प्राप्त करेंगे लेकिन यह भी एक गलती देता है।
  • objectRegisteredForID:nil वापस करेगा यदि ऑब्जेक्ट पहले से ही संदर्भ में नहीं है।

तो, अगर मैं एक पाश में या तो objectWithID: या existingObjectWithID:error: का उपयोग की वस्तुओं का एक समूह प्राप्त करने के लिए, जो संभावित रूप से मौजूदा दुकान में n यात्राएं वस्तुओं गलती करने के लिए है, जिसका अर्थ प्रदर्शन संभावित भयानक होने जा रहा है। अगर मैं objectRegisteredForID: का उपयोग करता हूं तो मुझे ऑब्जेक्ट बिल्कुल नहीं मिल सकता है अगर यह मुख्य कतार के एमओसी में पहले से नहीं होता है।

तो, सरणी पर पुनरावृत्ति करने की कोशिश करने के बजाय, मुझे उम्मीद है कि एक प्राप्त अनुरोध निरंतर स्टोर के साथ बातचीत करने के ऊपरी हिस्से को सीमित करेगा और मुझे आवश्यक सभी वस्तुओं को वापस करने में मदद मिलेगी।

अलावा:

के रूप में एक अलग रूप में, इस मुद्दे वास्तव में लगता है जैसे यह @"self IN %@" विधेय के साथ क्या करना है, के बाद से मुझे लगता है कि विधेय को हटा दें और इस मुद्दे को बिना entityName की सभी वस्तुओं को लाने कर सकते हैं। मैंने @"objectID IN %@" को उसी (शून्य) परिणामों के साथ पूर्वानुमान के रूप में भी आजमाया है।

+0

आपका वस्तु एक उचित वस्तु की तरह नहीं लगती है। शून्य 'इकाई' एक सुराग है: आपकी ऑब्जेक्ट आईडी के बारे में कुछ ख़राब है। आपका पोस्ट कोड ठीक दिखता है। क्या 'फू' इकाई सही है? – Mundi

+0

@Mundi आपको क्या लगता है कि वस्तु सही नहीं है?मैंने obj की पीओ की आपूर्ति नहीं की क्योंकि यह वास्तव में वस्तु को प्रिंट करता है और यह यहां बहुत अधिक जानकारी साझा कर रहा है। "फू" असली इकाई नाम नहीं है, लेकिन फू को खोज और प्रतिस्थापित करके प्रतिस्थापित किया गया था (केवल नाम आईपी की रक्षा के लिए बदल दिए गए हैं)। धन्यवाद। – levigroker

+0

तथ्य यह है कि 'इकाई' विशेषता शून्य है, यह बेहद संदिग्ध है। मुझे यकीन नहीं है कि इसका क्या कारण होगा, लेकिन यह आईडी ऑब्जेक्ट्स को किसी तरह से फर्जी या टूटा होने का संदेह करता है। –

उत्तर

12

ठीक है, कोर डेटा खरगोश छेद के नीचे एक यात्रा के लिए तैयार है?

टी एल; डॉ

NSManagedObjectID रों जिसका लगातार दुकान समन्वयक स्मृति में नहीं रह गया है, भले ही एक अलग लगातार दुकान समन्वयक से NSManagedObjectID रों करने के लिए अपने NSEntityDescription (entity) और समानता नहीं है (isEqual: रिटर्न NO) खोना उनके URIRepresentation समान हैं।

नीचे रैबिट होल

मीठा ... यहाँ हम चले।

याद रखें, मैं एक अलग थ्रेड पर एक अलग प्रबंधित ऑब्जेक्ट संदर्भ (एमओसी) से ऑब्जेक्ट आईडी की सरणी एकत्र कर रहा हूं? अच्छा। हालांकि, मैंने उल्लेख नहीं किया कि एमओसी अपने स्वयं के पर्सिस्टेंट स्टोर कोऑर्डिनेटर (पीएससी) का उपयोग कर रहा है (बिल्कुल उसी फाइल पर इंगित करता है)। एक बार जब काम पूरा हो जाता है तब से पीएससी और एमओसी कम रहता है, लेकिन वे जीवित रहते हैं, लेकिन NSManagedObjectID के उदाहरण NSArray (जो एक अलग थ्रेड में पारित हो जाते हैं) में सहेजते हैं।

एक बार अलग थ्रेड में प्राप्त होने के बाद, NSManagedObjectID के पास nil इकाई है। ऐसा प्रतीत होता है (शिक्षित अनुमान ...) क्योंकि पीएससी जिस से इन ऑब्जेक्ट्स आया है अब अब स्मृति में नहीं है और NSManagedObjectID को NSEntityDescription (entity) का एक सप्ताह संदर्भ रखना चाहिए जो पीएससी द्वारा आयोजित किया जाना चाहिए। nilentity रूप टिप्पणीकर्ताओं संदिग्ध, समस्याओं का कारण ...

मैं internals के बारे में सुनिश्चित नहीं किया जा सकता है, लेकिन यह लगता है कि entity बिना NSManagedObjectID एक और NSManagedObjectID के बराबर नहीं एक ही URIRepresentation साथ है । मुझे उदाहरण देकर स्पष्ट करते हैं:

निम्नलिखित कोड में: * objectID एक सतत् दुकान नहीं रह गया है जो स्मृति में और जिसका इकाई संपत्ति nil है से एक NSManagedObjectID * है। * managedObjectContext (बेशक)

NSURL *URIRep = objectID.URIRepresentation; 
NSManagedObjectID *newObjectID = [managedObjectContext.persistentStoreCoordinator managedObjectIDForURIRepresentation:URIRep]; 

अगर हम डीबगर में इसे देखो ... लगता है कि हमारे वर्तमान धागे पर हमारे एमओसी है क्या:

(lldb) p [ojectID isEqual:newObjectID] 
(bool) $0 = false 

हालांकि इन दो objectIDs की URIRepresentation समान होना चाहिए, वस्तुएं समान नहीं हैं।

यह लगभग निश्चित रूप से क्यों है [NSPredicate predicateWithFormat:@"self IN %@", objectIDs] किसी ऑब्जेक्ट से मेल खाने में विफल रहा है और fetch अनुरोध शून्य ऑब्जेक्ट्स को वापस करने का अनुरोध कर रहा है।

एक NSManagedObjectID * दिलचस्प बात यह है, तथापि, निम्नलिखित कोड में, जहां testID है एक सतत् दुकान नहीं रह गया है जो स्मृति में और जिसका इकाई संपत्ति nil है, वस्तु मुद्दा बिना एमओसी से लिया गया है से:

NSManagedObject *obj = [managedObjectContext existingObjectWithID:testID error:&error]; 

वर्कअराउंड

वहाँ दो चीजें हैं जो मैं इस के लिए एक समाधान के रूप सत्यापित करने के बाद कर रहे हैं:

  1. संदर्भों के बीच NSManagedObjectID एस संचारित करते समय एक ही पर्सिस्टेंट स्टोर कोऑर्डिनेटर (पीएससी) का उपयोग करें (और सुनिश्चित करें कि यह स्मृति में निवासी रहता है)। यदि यह किया जाता है, तो NSManagedObjectID कभी भी entity खो देता है और सब कुछ अपेक्षित काम करता है।

  2. संदर्भ से संदर्भ के लिए NSManagedObjectID एस पास करने के बजाय, उनके URIRepresentation का उपयोग करें। यानी NSManagedObjectID ऑब्जेक्ट्स की सरणी पास करने के बजाय, NSURL की एक सरणी को NSManagedObjectID के URIRepresentation का प्रतिनिधित्व करें। एक बार उन ऑब्जेक्ट्स के साथ लाने के लिए तैयार होने के बाद वर्तमान एमओसी के पीएससी से NSManagedObjectID प्राप्त करने के लिए managedObjectIDForURIRepresentation: संदेश का उपयोग करें।

विकल्प 1 सरल है, लेकिन संगामिति समय के साथ कुछ नुकसान हो सकता है और अगर, कहते हैं, आप अपने कार्यों के लिए एक अलग PSC जो केवल उदाहरण के लिए पढ़ने के लिए गया था, करना चाहते थे भी प्रतिबंधक हो सकता है।

मेरी (अपेक्षाकृत सीमित) अनुभव managedObjectIDForURIRepresentation: बुला में यह बहुत performant होने के लिए इतना NSManagedObjectID रों को बदलने URIRepresentationNSURL कि ज्यादा भूमि के ऊपर जोड़ने के लिए प्रतीत नहीं होता दिखाई देता है।

धन्यवाद

धन्यवाद के साथ पालन करने के लिए ... मैं यह स्पष्ट रूप से इस मुद्दे को और समाधानों की व्याख्या की सहायता करेगी। मुझे निश्चित रूप से लगता है कि मैंने कोर डेटा ऑब्जेक्ट आईडी और लगातार स्टोर समन्वयकों में एक मेरिट बैज अर्जित किया है और यह सब खोदकर खोद रहा है।

चीयर्स,

लेवी

+0

बहुत दिलचस्प है। मैं ऑब्जेक्ट आईडी मिलान करने में असफल होने के बारे में एक बग दर्ज करने का सुझाव देता हूं, क्योंकि उन्हें वास्तव में चाहिए। आपके परिणामों के आधार पर मुझे संदेह है कि 'मौजूदा ऑब्जेक्ट विथिड' वास्तव में यूआरआई प्रतिनिधित्व को पार करता है, जिससे अन्य विशेषता मान अप्रासंगिक होते हैं। यदि ** ** ** काम करता है, तो आपके fetch predicate काम करना चाहिए था, और 'isqual:' 'YES' वापस आना चाहिए। [मैंने कुछ समय पहले एक ऐसी ही बग दायर लेकिन मेरे मामले में यह विशेष रूप से संबंधित iCloud किया गया था।] –

+0

मैं पहली बार objectWithID तो विधेय में उस वस्तु का उपयोग करते हैं, एक और वैकल्पिक हल सुझाव देना चाहते हैं। अब हम पृष्ठभूमि संदर्भ में कमजोर फॉल्ट ओवरहेड, बैच फॉल्टिंग और प्रीफेचिंग का लाभ उठा सकते हैं। – malhal

संबंधित मुद्दे