यहाँ एक पूर्ण समाधान कैसे कोर डेटा के साथ एक अनुक्रमित तालिका प्रबंधन करने के लिए:
affectedObject.displayOrderValue = toIndex;
के बाद रखा जाना चाहिए: पहले
for (NSUInteger i = start; i <= end; i++) {
FFObject *otherObject = [self.fetchedResultsController.fetchedObjects objectAtIndex:i];
NSLog(@"Updated %@/%@ from %i to %i", otherObject.name, otherObject.state, otherObject.displayOrderValue, otherObject.displayOrderValue + delta);
otherObject.displayOrderValue += delta;
}
और । आपकी विशेषता displayOrder
कहलाती है, मैं इसे index
कहता हूं। सबसे पहले, आप बेहतर दृश्य नियंत्रक और मॉडल को अलग करते हैं। इसके लिए मैं एक मॉडल नियंत्रक का उपयोग करता हूं, जो दृश्य और मॉडल के बीच इंटरफ़ेस है।
ऐसे 3 मामले हैं जिन्हें आपको प्रबंधित करने की आवश्यकता है कि उपयोगकर्ता दृश्य नियंत्रक के माध्यम से प्रभावित हो सकता है।
- किसी मौजूदा ऑब्जेक्ट को हटाया जा रहा
- पुन: व्यवस्थित करें वस्तुओं एक नई वस्तु
- जोड़ा जा रहा है।
पहले दो मामले जोड़ना और हटाना बहुत सरल है। हटाए गए ऑब्जेक्ट के बाद इंडेक्स को अपडेट करने के लिए कॉल को renewObjectIndicesUpwardsFromIndex
नामक दिनचर्या हटाएं।
- (void)createObjectWithTitle:(NSString*)title {
FFObject* object = [FFObject insertIntoContext:self.managedObjectContext];
object.title = title;
object.index = [NSNumber numberWithInteger:[self numberTotalObjects]];
[self saveContext];
}
- (void)deleteObject:(FFObject*)anObject {
NSInteger objectIndex = [anObject.index integerValue];
[anObject deleteObject];
[self renewObjectIndicesUpwardsFromIndex:objectIndex];
[self saveContext];
}
- (void)renewObjectIndicesUpwardsFromIndex:(NSInteger)fromIndex {
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext]];
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"(index > %d)", fromIndex];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"index" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSError* fetchError = nil;
NSArray* objects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];
NSInteger index = fromIndex;
for (FFObject* object in objects) {
object.index = [NSNumber numberWithInteger:index];
index += 1;
}
[self saveContext];
}
पुन: आदेश के लिए नियंत्रक दिनचर्या में आने से पहले, यहां दृश्य नियंत्रक में हिस्सा शामिल है। मैं एक बूल isModifyingOrder
this answer के समान उपयोग करता हूं। ध्यान दें कि व्यू कंट्रोलर नियंत्रक moveObjectOrderUp
और moveObjectOrderDown
में दो फ़ंक्शन कॉल करता है। तालिका दृश्य में ऑब्जेक्ट्स को प्रदर्शित करने के तरीके के आधार पर - नवीनतम सबसे पहले या नवीनतम अंतिम - आप उन्हें स्विच कर सकते हैं।
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
isModifyingOrder = YES;
NSUInteger fromIndex = sourceIndexPath.row;
NSUInteger toIndex = destinationIndexPath.row;
if (fromIndex == toIndex) {
return;
}
FFObject *affectedObject = [self.fetchedResultsController.fetchedObjects objectAtIndex:fromIndex];
NSInteger delta;
if (fromIndex < toIndex) {
delta = toIndex - fromIndex;
NSLog(@"Moved down by %lu cells", delta);
[self.objectController moveObjectOrderUp:affectedObject by:delta];
} else {
delta = fromIndex - toIndex;
NSLog(@"Moved up by %lu cells", delta);
[self.objectController moveObjectOrderDown:affectedObject by:delta];
}
isModifyingOrder = NO;
}
और यहां नियंत्रक में हिस्सा। यह अच्छा लिखा जा सकता है, लेकिन यह समझने के लिए शायद सबसे अच्छा है।
- (void)moveObjectOrderUp:(FFObject*)affectedObject by:(NSInteger)delta {
NSInteger fromIndex = [affectedObject.index integerValue] - delta;
NSInteger toIndex = [affectedObject.index integerValue];
if (fromIndex < 1) {
return;
}
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext]];
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"(index >= %d) AND (index < %d)", fromIndex, toIndex];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"index" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSError* fetchError = nil;
NSArray* objects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];
for (FFObject* object in objects) {
NSInteger newIndex = [object.index integerValue] + 1;
object.index = [NSNumber numberWithInteger:newIndex];
}
affectedObject.index = [NSNumber numberWithInteger:fromIndex];
[self saveContext];
}
- (void)moveObjectOrderDown:(FFObject*)affectedObject by:(NSInteger)delta {
NSInteger fromIndex = [affectedObject.index integerValue];
NSInteger toIndex = [affectedObject.index integerValue] + delta;
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext]];
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"(index > %d) AND (index <= %d)", fromIndex, toIndex];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"index" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSError* fetchError = nil;
NSArray* objects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];
for (FFObject* object in objects)
{
NSInteger newIndex = [object.index integerValue] - 1;
object.index = [NSNumber numberWithInteger:newIndex];
}
affectedObject.index = [NSNumber numberWithInteger:toIndex];
[self saveContext];
}
कुछ भी करने को कदम अधिसूचना को रोकने के लिए हटाएं क्रिया के लिए अपनी व्यू नियंत्रक में एक दूसरे BOOL
उपयोग करने के लिए मत भूलना। मैं इसे isDeleting
कहता हूं और इसे यहां डालता हूं।
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
if (isModifyingOrder) return;
...
switch(type) {
...
case NSFetchedResultsChangeMove:
if (isDeleting == false) {
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:localIndexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:localNewIndexPath]withRowAnimation:UITableViewRowAnimationFade];
}
break;
...
}
}
शानदार! यह पूरी तरह से काम किया। मैं बहुत लंबे समय तक मूल कोड पर बहुत अधिक देख रहा था - आपकी मदद के लिए धन्यवाद। –
इसे http://stackoverflow.com/questions/1077568/how-to-implement-re-ordering-of-coredata-records/2013070#2013070 –
के साथ समानांतर में कार्यान्वित किया जाना चाहिए यदि आइटम हटाया जा सकता है, तो यह नहीं है काम। पंक्ति को हटाने पर आपको ऑर्डर फ़ील्ड को भी अपडेट करना सुनिश्चित करना होगा। – Kamchatka