我正在使用魔法记录将大量数据保存到我的数据库中。我想将它保存在后台,但它冻结了UI。我使用
保存它[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
} completion:^(BOOL success, NSError *error) {
}];
所以它不应该阻止UI。但我发现它使用主线程出于某些原因合并更改或类似的东西。如果有人能提出如何提高效率的解决方案,我将非常感激。
我正在使用的代码:
- (void)saveRidesForUser:(User *)user fromResponseData:(id)responseData
{
if (![[[responseData valueForKey:@"rides"] class] isSubclassOfClass:[NSArray class]]) {
return;
}
NSArray *rides = [responseData valueForKey:@"rides"];
if (!rides)
return;
NSMutableArray *photoCacheArray = [[NSMutableArray alloc] init];
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
User *rideUser = [user MR_inContext:localContext];
for (NSDictionary *rideDictionary in rides) {
Ride *ride = [Ride MR_createEntityInContext:localContext];
ride.title = ([rideDictionary objectForKey:@"title"]) ? [rideDictionary valueForKey:@"title"] : @"";
NSNumber *rideTimeStamp =[rideDictionary objectForKey:@"start_date"];
if (rideTimeStamp)
ride.startDate = [NSDate dateWithTimeIntervalSince1970:[rideTimeStamp doubleValue]];
NSNumber *rideEndTimeStamp =[rideDictionary objectForKey:@"end_date"];
if (rideEndTimeStamp)
ride.endDate = [NSDate dateWithTimeIntervalSince1970:[rideEndTimeStamp doubleValue]];
ride.serverID = [NSNumber numberWithInt:[[rideDictionary objectForKey:@"id"] intValue]];
ride.isPopular = [NSNumber numberWithBool:NO];
if ([rideDictionary objectForKey:@"intervals"]) {
NSArray *intervals = [rideDictionary objectForKey:@"intervals"];
for (NSDictionary *intervalDictionary in intervals) {
RideInterval *interval = [RideInterval MR_createEntityInContext:localContext];
interval.startDate = [NSDate dateWithTimeIntervalSince1970:[[intervalDictionary objectForKey:@"start_date"] integerValue]];
interval.endDate = [NSDate dateWithTimeIntervalSince1970:[[intervalDictionary objectForKey:@"end_date"] integerValue]];
interval.ride = ride;
if ([intervalDictionary objectForKey:@"points"] && ![[[intervalDictionary objectForKey:@"points"] class] isSubclassOfClass:[NSString class]]) {
NSArray *points = [intervalDictionary objectForKey:@"points"];
for (NSDictionary *pointDict in points) {
NSDictionary *pointDictionary = [pointDict dictionaryByReplacingNullsWithStrings];
RidePoint *point = [RidePoint MR_createEntityInContext:localContext];
point.timestamp = [NSDate dateWithTimeIntervalSince1970:[[pointDictionary objectForKey:@"timestamp"] integerValue]];
point.latitude = [NSNumber numberWithDouble:[[pointDictionary objectForKey:@"latitude"] doubleValue]];
point.longitude = [NSNumber numberWithDouble:[[pointDictionary objectForKey:@"longitude"] doubleValue]];
point.distanceFromPrevious = [NSNumber numberWithDouble:[[pointDictionary objectForKey:@"distance_from_previous"] doubleValue]];
point.interval = interval;
}
}
}
}
if ([rideDictionary valueForKey:@"photos"] && [[[rideDictionary valueForKey:@"photos"] class] isSubclassOfClass:[NSArray class]]) {
NSArray *photos = [rideDictionary objectForKey:@"photos"];
for (NSDictionary *photoDict in photos) {
NSDictionary *photoDictionary = [photoDict dictionaryByReplacingNullsWithStrings];
RidePhoto *photo = [RidePhoto MR_createEntityInContext:localContext];
photo.caption = [photoDictionary valueForKey:@"caption"];
NSNumber *timeStamp =[photoDictionary objectForKey:@"timestamp"];
if (timeStamp)
photo.timestamp = [NSDate dateWithTimeIntervalSince1970:[timeStamp doubleValue]];
photo.locationLatitude = [NSNumber numberWithDouble:[[photoDictionary objectForKey:@"location_latitude"] doubleValue]];
photo.locationLongitude = [NSNumber numberWithDouble:[[photoDictionary objectForKey:@"location_longitude"] doubleValue]];
photo.serverPath = [photoDictionary objectForKey:@"url"];
photo.imagePath = [NSString getUUID];
photo.ride = ride;
[photoCacheArray addObject:photo];
}
}
ride.user = rideUser;
}
} completion:^(BOOL success, NSError *error) {
[[NSNotificationCenter defaultCenter] postNotificationName:kLTRideServise_RoutesDownloadedNotification object:nil userInfo:nil];
}];
}
提前感谢您的帮助!
答案 0 :(得分:0)
您是否正在使用MR_defaultContext进行所有其他主线程任务?
我使用saveWithBlock:方法进行后台保存,MR_defaultContext用于主线程操作,它运行正常。据我所知,MagicalRecord在保存操作结束时将localContext与defaultContext合并。
示例代码:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.0 * NSEC_PER_SEC),
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
// your loop here in background thread
} completion:^(BOOL success, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
// completion on main thread
});
}];
});
答案 1 :(得分:0)
[[NSNotificationCenter defaultCenter] postNotificationName:kLTRideServise_RoutesDownloadedNotification object:nil userInfo:nil];
==>检查完成时您正在进行的处理。在主线程上调用此通知,可能是您正在进行大量处理,导致主线程忙,导致UI冻结。
同时检查您是否已从任何上下文注册NSManagedObjectContextDidSaveNotification,并查看您是否在那里进行任何处理。
答案 2 :(得分:0)
我正在使用
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreWithCompletion:aCallback];
将上下文保存到数据库中。
记录如下
/// \brief Asynchronously save changes in the current context all the way back to the persistent store /// \param completion Completion block that is called after the save has completed. The block is passed a success state as a `BOOL` and an `NSError` instance if an error occurs. Always called on the main queue. /// \discussion Executes asynchronous saves on the current context, and any ancestors, until the changes have been persisted to the assigned persistent store. The completion block will always be called on the main queue.
这对我来说很好,没有任何冻结。