2012-09-14 20 views
8

अपडेट के बाद नए आवेषण/हटाए गए मानों को हटा नहीं देता है, ऐसे प्रश्नों के दर्जनों पढ़ने के बाद, मैं इस कथन से शुरुआत करना चाहता हूं: "मैंने NSFetchedResultsController के प्रतिनिधि को सेट किया है, यह काम नहीं करता है।" ।NSFetchedResultsController को

तो मैं एक साधारण TableViewController जिसका कोशिकाओं NSFetchedResultsController से भर रहे हैं की है।

@property (strong, nonatomic) NSFetchedResultsController *frc; 

... 

- (NSFetchedResultsController *)frc 
{ 
    if (!_frc) 
    { 
     NSError *error = nil; 
     NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:e_product]; 
     request.sortDescriptors = [NSArray arrayWithObjects: 
           [NSSortDescriptor sortDescriptorWithKey:@"product_group.product_group_name" ascending:YES], 
           [NSSortDescriptor sortDescriptorWithKey:f_product_name ascending:YES], 
           nil]; 
     _frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[DTGGlobalSettings sharedInstance].moc sectionNameKeyPath:@"product_group.product_group_name" cacheName:nil]; 
     _frc.delegate = self; 
     [_frc performFetch:&error]; 
     if (error) 
     { 
      NSLog(@"Error while fetching products: %@!", error.userInfo); 
     } 
    } 

    return _frc; 
} 

मैं भी है NSFetchedResultsController प्रतिनिधि तरीकों कुछ डिबगिंग लेबल के साथ लागू किया:: यहाँ एफआरसी init कोड है

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates. 
    NSLog(@"controllerWillChangeContent"); 
    [self.tableView beginUpdates]; 
} 


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 

    UITableView *tableView = self.tableView; 

switch(type) { 

    case NSFetchedResultsChangeInsert: 
     NSLog(@"didChangeObject - insert"); 
     [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeDelete: 
     NSLog(@"didChangeObject - delete"); 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeUpdate: 
     NSLog(@"didChangeObject - update"); 
     [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 
     break; 

    case NSFetchedResultsChangeMove: 
     NSLog(@"didChangeObject - move"); 
     [tableView deleteRowsAtIndexPaths:[NSArray 
              arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     [tableView insertRowsAtIndexPaths:[NSArray 
              arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
} 
} 


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { 

switch(type) { 

    case NSFetchedResultsChangeInsert: 
     NSLog(@"didChangeSection - insert"); 
     [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeDelete: 
     NSLog(@"didChangeSection - delete"); 
     [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
} 
} 


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 
// The fetch controller has sent all current change notifications, so tell the table view to process all updates. 
NSLog(@"controllerDidChangeContent"); 
[self.tableView endUpdates]; 
} 

मेरी navigationBar में मैं ताज़ा करें बटन है, अपने कार्य उत्पाद सूची तक सक्रिय किया जाता है विधि है जो निम्नलिखित है: 1. दूरस्थ MySQL सर्वर 2. आईडी के साथ उत्पाद मौजूद नहीं है, तो से उत्पादों को हासिल करेगा - यह बनाता है और सभी क्षेत्रों 3. अगर यह मौजूद है भरता है, सभी क्षेत्रों के अनुसार अपडेट किया जाता है प्राप्त मूल्य

पंक्ति 2 के बाद और 3 दुकान सहेजा गया है। मैं ऐप में सभी कोरडाटा संचालन के लिए एकल NSManagedObjectContext का उपयोग करता हूं।

जब मैं पहली बार ऐप शुरू करता हूं, टीवीसी खाली है, क्योंकि अभी तक कोई उत्पाद नहीं मिला है। जब मैं रीफ्रेश करें दबाएं, नए उत्पादों प्राप्त किए गए और ManagedObjectContext में डाला है, लेकिन NSManagedObjectContext नहीं देखता/कोई भी परिवर्तन सुना है: कोई प्रतिनिधि पद्धतियों को बुलाया जाता है, इसलिए कोई नई पंक्तियाँ टीवीसी में जुड़ जाते हैं। जब मैं ऐप को पुनरारंभ करता हूं तो नए उत्पादों को बिना किसी समस्या के टीवीसी में लाया जाता है।

यदि मैं वहां कुछ उत्पादों के साथ ताज़ा बटन दबाता हूं, तो थोड़ी देर के बाद वे सभी गायब हो जाते हैं। कुछ डिबगिंग ने मुझे दिखाया कि यदि इकाइयों के क्षेत्र को अद्यतन करने के बाद होता है (वास्तव में मूल्य समान होते हैं) और स्टोर को सहेजते हैं। प्रतिनिधि तरीकों एक आकर्षण की तरह इस बार काम और हर अपडेट और सहेज लिया इकाई नियंत्रक के लिए: didChangeObject: atIndexPath: forChangeType: newIndexPath साथ forChangeType = NSFetchedResultsChangeDelete कहा जाता है।

प्रश्न # 1: क्यों NSFetchedResultsController ऐप पुनरारंभ किए बिना सम्मिलित इकाइयों को नहीं देखता है? प्रश्न # 2: क्यों NSFetchedResultsController पहले से ही "गैर मौजूदा" (?) के रूप में संस्थाओं को लाता है और स्टोर सहेजने के बाद उन्हें टीवीसी से हटा देता है?

मैं, किसी भी मदद और विचारों की सराहना करेंगे पूरे पिछले सप्ताह के लिए इस मुद्दे के साथ लड़ रहे हैं; (

(जोड़ी के लिए) UPD1: यहाँ कुछ विवरण मैं कुछ वार्स साझा करने के लिए कस्टम वर्ग DTGGlobalSettings का उपयोग कर रहे हैं। ।

+(DTGGlobalSettings *)sharedInstance 
{ 
    static DTGGlobalSettings *myInstance = nil; 

    if (nil == myInstance) 
    { 
     myInstance = [[[self class] alloc] init]; 
     // set values here 
     // try to acces MOC to init CoreData 
     [myInstance moc];   
     myInstance.baseURL = @"http://local.app/"; 
} 
return myInstance; 
} 

CoreData ढेर init करने के लिए मैं एप्पल प्रलेखन से एक उदाहरण का इस्तेमाल किया है, क्योंकि किसी कारण से मैं चेकबॉक्स "CoreData उपयोग" एक नया बनाते समय नहीं दिख रहा है: एप्लिकेशन भर में इसी तरह मैं अपनी sharedInstance संपत्ति init है प्रोजेक्ट। मुझे यकीन है कि मैंने इसे एक्ससी में पहले देखा है स्तोत्र, लेकिन अब मुझे नहीं पता, ((Xcode 4.4.1):

#pragma mark Core Data stack 

- (NSManagedObjectContext *) moc { 

if (_moc != nil) { 
    return _moc; 
} 
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
if (coordinator != nil) { 
    _moc = [[NSManagedObjectContext alloc] init]; 
    [_moc setPersistentStoreCoordinator: coordinator]; 
} 
return _moc; 
} 


- (NSManagedObjectModel *)managedObjectModel { 

if (_managedObjectModel != nil) { 
    return _managedObjectModel; 
} 
_managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];  
return _managedObjectModel; 
} 


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 

if (_persistentStoreCoordinator != nil) { 
    return _persistentStoreCoordinator; 
} 
NSURL *storeUrl = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
storeUrl = [storeUrl URLByAppendingPathComponent:DOC_NAME]; 

NSError *error; 
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]]; 

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) { 
    NSLog(@"Error adding a store to the coordinator: %@, %@", error, error.userInfo); 
}   
return _persistentStoreCoordinator; 
} 

-(void)saveDataStore 
{ 
    NSError *error; 
    if (![self.moc save:&error]) NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
} 

'MOC' (ManagedObjectContext) DTGGlobalSettings की संपत्ति तो हर जगह अनुप्रयोग में मैं कहाँ CoreData के लिए उपयोग की जरूरत है प्रयोग किया जाता है।

अब दूसरे भाग में, डेटाबेस अद्यतन कर रहा है।मुझे रिमोट वेब-सर्वर से जेएसओएन प्रारूप में कुछ नई इकाइयां मिल रही हैं, परिणामस्वरूप शब्दकोश के माध्यम से जा रही हैं और अनुरोध परिणामों में मिली प्रत्येक इकाई के लिए createFromDictionary विधि को कॉल कर रही है। कोड यह रहा:

+(Product *)createFromDictionary:(NSDictionary *)entityData inContext:(NSManagedObjectContext *)moc performUpdate:(BOOL)update 
{ 
Product *result; 
if (update) 
{ 
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:e_product]; 
    request.predicate = [NSPredicate predicateWithFormat:@"%K = %@", f_product_id, [entityData objectForKey:f_product_id]]; 
    result = [[DTGGlobalSettings sharedInstance].moc executeFetchRequest:request error:nil].lastObject; 
    if (!result) 
    { 
     NSLog(@"Error updating Product ID %@! Cannot fetch entity.", [entityData objectForKey:f_product_id]); 
     return nil; 
    } 
} else 
{ 
    result = [NSEntityDescription insertNewObjectForEntityForName:e_product inManagedObjectContext:[DTGGlobalSettings sharedInstance].moc]; 
} 

result.product_id = [[DTGGlobalSettings sharedInstance].numFormatter numberFromString:[entityData objectForKey:f_product_id]]; 
result.product_image = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[DTGGlobalSettings sharedInstance].baseURL stringByAppendingString:[entityData objectForKey:f_product_image]]]]; 
result.product_name = [entityData objectForKey:f_product_name]; 

return result; 
} 

जब मैं fethed संस्थाओं से बाहर चलाने, मैं [[DTGGlobalSettings sharedInstance] saveDataStore] (ऊपर देखें) कहते हैं। इस बिंदु पर टीवीसी में मौजूदा पंक्तियां (यदि कोई थी) गायब हो रही थी। अगर मैं कुछ नई इकाइयों को जोड़ रहा था, तो कुछ भी नहीं बचा है, यानी टीवीसी अपनी पंक्तियों को अपडेट नहीं करता है।

+0

आपने गलत कोड पोस्ट किया है। दिलचस्प बिट्स यह है कि आप अपने डेटाबेस में डेटा कैसे आयात करते हैं, और आयात और प्राप्त किए गए परिणाम नियंत्रक दोनों के लिए कोर डेटा स्टैक कैसे सेट करते हैं। –

+0

मैंने यूपीडी 1 में आपके द्वारा पूछे गए कुछ विवरण जोड़े। मुझे उम्मीद है कि अब यह स्पष्ट है कि मैं इस के साथ कैसे समाप्त हुआ ... – Arseniy

+0

अद्यतन पर कोई विचार? – Arseniy

उत्तर

14

दरअसल, मुझे लगता है कि आपकी पहली प्री-एडिट पोस्टिंग में सभी आवश्यक जानकारी थीं। मैंने अभी इसे नहीं पढ़ा है (मुझे स्क्रॉलिंग को कोड की लंबी लाइनों को सही ढंग से पढ़ने की इच्छा नहीं है और कभी-कभी बस ऐसा नहीं करते - मेरा बुरा)।

आपकी समस्या आपके एफआरसी सॉर्ट डिस्क्रिप्टर से संबंधित प्रतीत होती है।

एफआरसी रिलेशनशिप सॉर्ट डिस्क्रिप्टर को बहुत अच्छी तरह अद्यतन करने के साथ अच्छी तरह से सौदा नहीं करता है।

कुछ ने तर्क दिया है कि यह कैसे बनाया गया है। मैं तर्क देता हूं कि यह एक बग है।

मेरे पोस्ट के लिए यह पोस्ट Changing a managed object property doesn't trigger NSFetchedResultsController to update the table view देखें। उम्मीद है कि आप अपने मामले में समानताएं देखेंगे।

+0

देखें यह आश्चर्यजनक है! मैंने बस क्रमशः सॉर्ट डिस्क्रिप्टर और सेक्शन नाम पथ हटा दिया और यह काम किया! मैं इस तरह के कामों का अनुमान कभी नहीं लगाऊंगा;) धन्यवाद! – Arseniy

+0

क्या यह समस्या अभी भी है? –

+0

हां। https://insanitysauce.files.wordpress.com/2013/09/bsxgx3vciaax5g5.jpg –

1

मैंने अभी एक ही मुद्दे के साथ समय बिताया और निम्नलिखित पाया: जब sectionNameKeyPath एक रिश्तेदार क्षेत्र का जिक्र कर रहा था जो nil मान ले सकता है, तो एफआरसी अपडेट ऑब्जेक्ट्स डालने पर काम नहीं करेगा।

यह एक्सकोड कंसोल में एक चेतावनी से संबंधित हो सकता है कि यह अनुभाग उस क्षेत्र के साथ nil पर ऑब्जेक्ट्स के लिए बनाया जाएगा। मुझे लगता है कि अनुभाग एफआरसी आंतरिक काम के साथ गड़बड़ कर देता है।

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