我的应用程序中有一个tableview,其中包含要加载到某些CoreData对象中的NSFetchedResultsController。

当表建立在cellForRowAtIndexPath:中时,我必须对每个单元格进行提取以从另一个对象获取其他信息。

该表充满了UserTasks,我必须从UserSite获取一些信息(UserTask包含siteID属性)

我正在后台线程中获取UserSite信息,并使用了临时上下文。它可以正常工作,但是在滚动时它仍然希望稍微落后于UI。

        Site *site = [_scannedSites objectForKey:task.siteID];
        if(!site)
        {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

                AppDelegate *ad = [AppDelegate sharedAppDelegate];
                NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
                temporaryContext.persistentStoreCoordinator = ad.persistentStoreCoordinator;

                Site *site2 = [task getSiteWithContext:temporaryContext];
                if(site2)
                {
                    [ad.managedObjectContext performBlock:^{

                        Site *mainContextObject = (Site *)[ad.managedObjectContext objectWithID:site2.objectID];
                        [_scannedSites mainContextObject forKey:task.siteID];
                    }];
                    dispatch_async(dispatch_get_main_queue(), ^{
                        Site *newSite = [_scannedSites objectForKey:task.siteID];
                        cell.lblCustName.text = newSite.siteName;
                        cell.lblAddr.text = [NSString stringWithFormat:@"%@ %@, %@", newSite.siteAddressLine1, newSite.siteCity, newSite.siteState];
                        cell.lblPhone.text = [self formatPhoneNum:newSite.phone];
                    });
                }
                else
                {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        cell.lblCustName.text = @"";
                        cell.lblAddr.text = @"";
                        cell.lblPhone.text = @"";
                    });
                }
            });
        }
        else
        {
            cell.lblCustName.text = site.siteName;
            cell.lblAddr.text = [NSString stringWithFormat:@"%@ %@, %@", site.siteAddressLine1, site.siteCity, site.siteState];
            cell.lblPhone.text = [self formatPhoneNum:site.phone];
        }


如您所见,如果您在_scannedSites中还没有某个任务的UserSite信息,则会启动一个后台线程,该线程将获取该任务的UserSite,将其存储起来,然后在主线程中填写详细信息。

就像我说的那样,滚动时会有一个非常烦人的滞后...我希望通过在后台进行工作来避免。

我会以错误的方式处理吗?

谢谢,任何建议表示赞赏。



编辑
我在CoreData中创建了一个关系,现在在cellForRowAtIndexPath中使用它。如果尚不存在,请创建它。这工作得更好。

    Site *site = task.site;
    if(!site)
    {
        AppDelegate *ad = [AppDelegate sharedAppDelegate];
        NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        temporaryContext.persistentStoreCoordinator = ad.persistentStoreCoordinator;

        [temporaryContext performBlock:^{

            Site *tempContextSite = [task getSiteWithContext:temporaryContext];

            [ad.managedObjectContext performBlock:^{
                Site *mainManagedObject = (Site *)[ad.managedObjectContext objectWithID:tempContextSite.objectID];
                task.site = mainManagedObject;
                NSError *error;
                if (![temporaryContext save:&error])
                {
                }
                [ad.managedObjectContext performBlock:^{
                    NSError *e = nil;
                    if (![ad.managedObjectContext save:&e])
                    {

                    }
                    dispatch_async(dispatch_get_main_queue(), ^{
                        cell.lblCustName.text = mainManagedObject.siteName;
                        cell.lblAddr.text = [NSString stringWithFormat:@"%@ %@, %@", mainManagedObject.siteAddressLine1, mainManagedObject.siteCity, mainManagedObject.siteState];
                        cell.lblPhone.text = [self formatPhoneNum:mainManagedObject.phone];
                    });
                }];
            }];
        }];
    }
    else
    {
        cell.lblCustName.text = site.siteName;
        cell.lblAddr.text = [NSString stringWithFormat:@"%@ %@, %@", site.siteAddressLine1, site.siteCity, site.siteState];
        cell.lblPhone.text = [self formatPhoneNum:site.phone];
    }

最佳答案

如果UserTaskUserSite有关,通常的Core Data方法将是在两者之间创建一个关系,然后在运行时使用该关系。因此,UserTask将具有一个名为site的属性,而您只需要向特定实例询问该属性的值即可。 ID属性可能仍然存在,但仅在与某些外部数据存储区(例如服务器API)同步时才使用。

这样存储ID并查找对象是一种从根本上很尴尬的方法,这种方法的设计目的是在运行时执行许多不必要的工作。它避免了Core Data试图提供的所有便利,而是用困难的方式处理事情。在表滚动时执行此工作也可能是最糟糕的时间,因为这是性能问题最明显的时刻。

如果由于某种原因必须以这种方式执行此操作,则可以通过提前查找所有UserSite实例而不是在滚动表时进行优化。如果您知道所有UserTask实例,请在加载视图时一次调用所有站点。

08-17 21:54