0

我的应用程序中有一个表格视图,其中包含一个 NSFetchedResultsController 以加载一些 CoreData 对象。

随着表格的建立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];
        }    

如您所见,如果您还没有任务的 UserSite 信息,则会_scannedSites启动一个后台线程,该线程会获取该任务的 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];
    }
4

2 回答 2

1

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

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

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

于 2013-05-03T18:37:10.567 回答
1

cellForRowAtIndexPath:. 如果用户滚动,将会创建一大堆线程,这些线程甚至可能没有必要。

最好有一个后台进程来获取您想要的信息,然后在需要时通知 UI 进行自我更新。这是非常标准的东西,你会很容易找到很多可靠实现的例子。

于 2013-05-03T18:40:01.740 回答