0

我有,我用它來保持和移動細胞在我的表視圖,以不同的指標,看起來像這樣的方法:如何將保存我的對象的NSFetchResultController數組更改爲我的對象的不同索引?

- (void)moveTableView:(FMMoveTableView *)tableView moveRowFromIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { 
NSArray *allObjects = [self.fetchedResultController fetchedObjects]; 
//array to hold the new order  
NSMutableArray * arrayCorectOrder = [NSMutableArray new]; 
//the target object that is in the index we are moving from 
Target *target = [self.fetchedResultController objectAtIndexPath:fromIndexPath]; 
} 

我有一個coreDataStack類,它的所有的核心數據的東西護理(創建singelton),它看起來像這樣:

#import "CoreDataStack.h" 

@implementation CoreDataStack 

#pragma mark - Core Data stack 

@synthesize managedObjectContext = _managedObjectContext; 
@synthesize managedObjectModel = _managedObjectModel; 
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 

+ (instancetype)defaultStack { 

    static CoreDataStack *defaultStack; 
    static dispatch_once_t onceTocken; 
    dispatch_once (&onceTocken, ^{ 
     defaultStack = [[self alloc] init]; 
    }); 

    return defaultStack; 
} 


- (NSURL *)applicationDocumentsDirectory { 
    // The directory the application uses to store the Core Data store file. This code uses a directory named "digitalCrown.Lister" in the application's documents directory. 
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
} 

- (NSManagedObjectModel *)managedObjectModel { 
    // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. 
    if (_managedObjectModel != nil) { 
     return _managedObjectModel; 
    } 
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Lister" withExtension:@"momd"]; 
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
    return _managedObjectModel; 
} 

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 
    // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. 
    if (_persistentStoreCoordinator != nil) { 
     return _persistentStoreCoordinator; 
    } 

    // Create the coordinator and store 

    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Lister.sqlite"]; 
    NSError *error = nil; 
    NSString *failureReason = @"There was an error creating or loading the application's saved data."; 
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 
     // Report any error we got. 
     NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 
     dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data"; 
     dict[NSLocalizedFailureReasonErrorKey] = failureReason; 
     dict[NSUnderlyingErrorKey] = error; 
     error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict]; 
     // Replace this with code to handle the error appropriately. 
     // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    } 

    return _persistentStoreCoordinator; 
} 


- (NSManagedObjectContext *)managedObjectContext { 
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) 
    if (_managedObjectContext != nil) { 
     return _managedObjectContext; 
    } 

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

#pragma mark - Core Data Saving support 

- (void)saveContext { 
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext; 
    if (managedObjectContext != nil) { 
     NSError *error = nil; 
     if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 
      // Replace this implementation with code to handle the error appropriately. 
      // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      abort(); 
     } 
    } 
} 


@end 

,每當我新對象添加到核心數據我做這種方式:表視圖時

- (void)insertTeget { 

    CoreDataStack *stack = [CoreDataStack defaultStack]; 
    Target *target = [NSEntityDescription insertNewObjectForEntityForName:@"Target" inManagedObjectContext:stack.managedObjectContext]; 
    if (self.myTextView.text != nil) { 
     target.body = self.myTextView.text; 
     target.time = [NSDate date]; 
    } 

    [stack saveContext]; 

} 

我獲取數據我做這種方式:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 


    static NSString *cellIdentifier = @"StackTableViewCell"; 

    Target *target = [self.fetchedResultController objectAtIndexPath:indexPath]; 

    StackTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 

    if (!cell) 
    { 
     NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"StackTableViewCell" owner:self options:nil]; 
     cell = [topLevelObjects objectAtIndex:0]; 
    } 

    cell.cellLabel.text = target.body; 

    cell.cellLabel.font = [UIFont fontWithName:@"Candara-Bold" size:20]; 

    cell.showsReorderControl = YES; 



    // Configure the cell... 

    return cell; 
} 

這是我fetchresultconroller /取表視圖控制器類的要求配置:

- (NSFetchRequest *)targetsFetchRequest { 

    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Target"]; 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"time" ascending:YES]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 
    [fetchRequest setSortDescriptors:sortDescriptors]; 
    return fetchRequest; 
} 


- (NSFetchedResultsController *)fetchedResultController { 

    if (_fetchedResultController != nil) { 
     return _fetchedResultController; 
    } 

    CoreDataStack *stack = [CoreDataStack defaultStack]; 

    NSFetchRequest *fetchRequest = [self targetsFetchRequest]; 

    _fetchedResultController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:stack.managedObjectContext sectionNameKeyPath:nil cacheName:nil]; 

    _fetchedResultController.delegate = self; 

    return _fetchedResultController; 

} 

,現在我的魔杖檢查順序被更改了,所以我需要更改數據庫中的順序...

我該如何做?

謝謝!

+0

您在獲取的結果控制器配置中指定了什麼排序?如果您允許用戶對行進行重新排序,您需要在實體上有一個屬性(例如'index'或'sortOrder'),您可以修改該屬性以反映所選的順序,並且您應該使用此屬性作爲關鍵字在FRC中排序。 – pbasdf 2015-04-05 11:34:35

+0

說實話,我真的是初學者,所以我不確切地回答你的問題,所以我只是給我的問題添加更多的解釋,也許會幫助你更多地瞭解:) – Joe 2015-04-05 11:52:39

+0

謝謝。你還可以在創建和配置fetchedResultsController的地方添加代碼嗎? – pbasdf 2015-04-05 12:00:25

回答

0

根據我的意見,提取的結果控制器根據底層提取的排序順序爲每個對象創建indexPath - 在您的案例中爲time。如果您希望用戶能夠覆蓋此行並對行重新排序,請將FRC更改爲使用不同的排序順序。向您的實體添加一個名爲sortTime的新屬性(日期類型),並修改targetsFetchRequest方法以使用sortTime作爲排序關鍵字。

每當您添加新的Target時,請同時設置sortTime。在重新排序行時,請設置值sortTime以確保FRC將目標放置在新的indexPath處。例如:

-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { 
    Target *targetToMove = [self.fetchedResultsController objectAtIndexPath:sourceIndexPath]; 
    if (destinationIndexPath.row == 0) { 
     // to move to row 0, the new sortTime can be any value 
     // that is less than the sortTime of the Target currently at 
     // row 0 
     Target *targetAtRow0 = [self.fetchedResultsController objectAtIndexPath:destinationIndexPath]; 
     targetToMove.sortTime = [targetAtRow0.sortTime dateByAddingTimeInterval:-1]; 
    } else { 
     // for any other row, set the sortTime to be half way 
     // between the sortTime for the row before the new position 
     // and the sortTime for the row at the new position 
     Target *targetBefore = [self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:(destinationIndexPath.row-1) inSection:destinationIndexPath.section]]; 
     Target *targetAfter = [self.fetchedResultsController objectAtIndexPath:destinationIndexPath]; 
     double lowerTimeInterval = [targetBefore.sortTime timeIntervalSinceReferenceDate]; 
     double upperTimeInterval = [targetAfter.sortTime timeIntervalSinceReferenceDate]; 
     double newInterval = (lowerTimeInterval + upperTimeInterval)/2; 
     NSDate *newSortTime = [NSDate dateWithTimeIntervalSinceReferenceDate:newInterval]; 
     targetToMove.sortTime = newSortTime; 
    } 
    NSError *error; 
    if (![self.managedObjectContext save:&error]) { 
     NSLog(@"SaveContext: error %@, %@", error, [error userInfo]); 
     abort(); 
    } 
} 

這應該會觸發FRC委託方法執行必要的表視圖更新。

0

我建議你考慮增加另一個屬性到你的實體Target,或許稱它爲「sortOrder」?

當您提取結果時,請考慮按sortOrder排序。

要做到這一點,您需要在創建每個實體時設置sortOrder的值。這應該是相對簡單的...在創建實體之前完成fetchedResults的計數,假設您的下一個sortOrder值將等於計數值加1.

當您在tableview中移動一行時,可以使用代碼重新分配受影響的單元格的sortOrder值等於indexPath.row屬性。

保存後,您的新排序順序應該保留。

相關問題