iOS:保存托管对象上下文需要一段时间后超过1秒

Mic*_*iZH 1 core-data objective-c uitableview nsfetchedresultscontroller ios

奇怪的问题,奇怪的是从昨天开始.我有一个获取结果控制器,您可以在其中重新排序行没有任何问题.在应用程序重新开始之后,一切都运行良好而快速.但是,如果您从此选项卡栏更改为另一个选项卡栏并编辑一些随机文本字段(甚至没有链接到核心数据并且不会触发任何保存),则重新排序非常慢.而我只能将其缩小到保存环境.但现在我不知道在哪里可以看得更远.有什么建议?这是我的重新排序功能:

- (void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
      toIndexPath:(NSIndexPath *)destinationIndexPath;
{
    if (self.activeField && [self.activeField isFirstResponder]){
        [self.activeField resignFirstResponder];
    }

    self.suspendAutomaticTrackingOfChangesInManagedObjectContext = YES;

    //Makes only a mutable copy of the array, but NOT the objects (references) within
    NSMutableArray *fetchedResults = [[self.fetchedResultsController fetchedObjects] mutableCopy];

    // Grab the item we're moving
    NSManagedObject *resultToMove = [self.fetchedResultsController objectAtIndexPath:sourceIndexPath];

    // Remove the object we're moving from the array.
    [fetchedResults removeObject:resultToMove];
    // Now re-insert it at the destination.
    [fetchedResults insertObject:resultToMove atIndex:[destinationIndexPath row]];

    // All of the objects are now in their correct order. Update each
    // object's displayOrder field by iterating through the array.
    int i = 1;
    for (MainCategory *fetchedResult in fetchedResults)
    {
        fetchedResult.position = [NSNumber numberWithInt:i++];
    }

    // Save
    TICK;
    [((AppDelegate *)[[UIApplication sharedApplication] delegate]) saveContext];
    TOCK;

    self.suspendAutomaticTrackingOfChangesInManagedObjectContext = NO;
}
Run Code Online (Sandbox Code Playgroud)

昨天我只插入了这两种方法(这不是问题,因为在评论它们之后它们不会触发,同样的问题仍然存在):

-(void) registerForKeyboardNotificationsWithTabBarHeight:(CGFloat)tabbarHeight andHeaderHeight:(CGFloat)headerHeight andFooterHeight:(CGFloat)footerHeight  andBottomSpacingToTextFields:(CGFloat)spacingToTextFields
{
    self.tabbarHeight = tabbarHeight;
    self.footerHeight = footerHeight;
    self.headerHeight = headerHeight;
    self.spacingToTextFields = spacingToTextFields;

    // Register notification when the keyboard will be show
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];

    // Register notification when the keyboard will be hide
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
Run Code Online (Sandbox Code Playgroud)

FetchedResultsController:

- (void)setupFetchedResultsController
{
    self.managedObjectContext = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext;

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MainCategory"];
    request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"position" ascending:YES]];

    self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request
                                                                       managedObjectContext:self.managedObjectContext
                                                                         sectionNameKeyPath:nil                                                                                  cacheName:@"MainCategoryCache"];
}
Run Code Online (Sandbox Code Playgroud)

而且会出现的观点也非常无害......

- (void)viewWillAppear:(BOOL)animated
{
    //Initialize database
    [super viewWillAppear:animated];

    [self displayBudget];

    /*
    This is only necessary since the sum of all categories is calculated and the FetchedResultsController
    doesn't get this since it's only monitoring a MainCategory and the changes occured in the Subcategories */
    [self.tableView reloadData];
}
Run Code Online (Sandbox Code Playgroud)

我很感谢任何线索可能是什么问题:-(

Mar*_*rra 5

在这种情况下我不建议使用多线程.问题是您的保存是在错误的时间完成的.将它们移动到后台队列并不能解决问题.您需要更改保存行为.

写入磁盘很昂贵.周围没有捷径.即使您将保存移动到另一个上下文(有一个Apple示例),他们仍然需要花时间并可能阻止您的UI(您在保存期间无法进行新的提取).您需要更改保存行为.

每次用户移动行时都不需要保存.这很浪费.您希望将保存排队,以便每次保存都执行更多操作.此外,当用户希望延迟时,您应该保存.推送或弹出视图时可能是保存的好时机.当你的应用程序进入后台是一个很好的保存时间.

当用户想要平滑的UI响应时保存是不好的并且导致糟糕的用户体验.寻找用户期待某些事情需要时间的机会.将内容发布到服务器?同时保存.

您NSFetchedResultsController等将从保存数据中读取未NSManagedObjectContext保存的数据.通过经常保存,您无法获得UI上的任何内容.

更新1

性能问题的第一步是在Instruments中运行您的应用程序.

测量速度,然后看看是什么花费你的时间.Time Profiler是你的朋友.