我在从数据库加载数据时使用多线程。
我正在做以下
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
// Get data
NSDate *pastDate = [CommonHelper getSelectedDateYearBackComponents:[NSDate date]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"users == %@ && startDate >= %@", objUser,pastDate];
NSMutableArray *fetchArray = [DataAccess searchObjectsInUserContext:@"userIngo" :predicate :@"startDate" :NO];
if ([fetchArray count] > 0)
{
dispatch_async(dispatch_get_main_queue(),
^{
// Reload table
[self.tableView reloadData]; });
}
else
{
dispatch_async(dispatch_get_main_queue(),
^{ // calling Webservice
});
}
});
其中users
是我尝试获取数据的实体,objUser是我从用户实体检索数据的用户对象
我的searchObjectsInUserContext代码就像这样
+(NSMutableArray *) searchObjectsInLabContext: (NSString*) entityName : (NSPredicate *) predicate : (NSString*) sortKey : (BOOL) sortAscending
{
i3EAppDelegate *appDelegate = (i3EAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setUndoManager:nil];
[context setPersistentStoreCoordinator:[appDelegate persistentStoreCoordinator]];
// Register context with the notification center
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(mergeChanges:) name:NSManagedObjectContextDidSaveNotification object:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
[request setEntity:entity];
[request setFetchBatchSize:10];
[request setReturnsObjectsAsFaults:NO];
// If a predicate was passed, pass it to the query
if(predicate != nil)
{
[request setPredicate:predicate];
}
// If a sort key was passed, use it for sorting.
if(sortKey != nil)
{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
}
NSError *error;
NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// Handle the error.
// NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
[request release];
appDelegate = nil;
return [mutableFetchResults autorelease];
}
因此,在我的searchObjectInUserContext中,我使用多个managedObjectContext,以便在Fred McCann在他的blog post中解释多线程时不会给我带来问题。
但是,我的问题是在我的searchObjectsInUserContext中NSMutableArray *mutableFetchResults
,因为即使数据库中有数据,它有时会返回0。
有人可以帮我解决我做错的事吗?
答案 0 :(得分:2)
你的获取没有任何问题,所以我怀疑这个问题可能是时间问题。这个fetch是在另一个线程保存之前运行的吗?这可以解释你所看到的行为。
另外,为什么你在后台线程上运行它?您是否看到需要像这样的后台搜索的性能问题?
首先,我仍然怀疑是否需要背景提取。这通常是在遇到性能问题时保留的,因为提取非常快。
其次,您获取后台队列,但之后您不会对所获取的数据执行任何操作。你不要把它交给桌子(无论如何都是坏的),你只需要把它扔掉。
如果您只是为了计数而不提取,请执行-[NSManagedObjectContext -countForFetchRequest: error:]
。它会更快,无需后台队列调用。
如果您希望对结果采取某些措施,则会遇到问题。 NSManagedObject
的实例无法跨越线程/队列边界。因此,获取后台队列对UI的影响很小。您需要来获取主队列/主线程上的这些对象。如果不这样做,您将崩溃,因为Core Data不允许它。
最后,你的背景队列对你造成的伤害大于弊,而且他们没有解决你想要解决的问题。