Ios 后台抓取比前台抓取导致应用程序冻结

Ios 后台抓取比前台抓取导致应用程序冻结,ios,objective-c,core-data,Ios,Objective C,Core Data,我已经在coredata中实现了后台抓取,但它仍然比正常抓取快了几秒钟。我能为快速抓取做些什么吗?看起来它仍然在前台抓取,不知道代码出了什么问题 - (void)sr_executeFetchRequest:(NSFetchRequest *)request completion:(void (^)(NSArray *objects, NSError *error))completion { NSString *loginUser=[[NSUserDefaults standardUserDe

我已经在coredata中实现了后台抓取,但它仍然比正常抓取快了几秒钟。我能为快速抓取做些什么吗?看起来它仍然在前台抓取,不知道代码出了什么问题

- (void)sr_executeFetchRequest:(NSFetchRequest *)request completion:(void (^)(NSArray *objects, NSError *error))completion {

NSString *loginUser=[[NSUserDefaults standardUserDefaults] valueForKey:@"currentUser"];

AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSPersistentStoreCoordinator *coordinator = [sharedDelegate persistentStoreCoordinator];
NSManagedObjectContext *context = [sharedDelegate managedObjectContext];

NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    backgroundContext.persistentStoreCoordinator = coordinator;

[backgroundContext performBlock:^{

    // Fetch into shared persistent store in background thread
    NSError *error = nil;
    //        NSLog(@"BG thread===== ");

    NSArray *fetchedObjects = [backgroundContext executeFetchRequest:request error:&error];

    [context performBlock:^{
        if (fetchedObjects) {
            // Collect object IDs
            NSMutableArray *mutObjectIds = [[NSMutableArray alloc] initWithCapacity:[fetchedObjects count]];
            for (NSManagedObject *obj in fetchedObjects) {
                [mutObjectIds addObject:obj.objectID];
    //                    NSLog(@"BG bg===== ");

            }

            // Fault in objects into current context by object ID as they are available in the shared persistent store
            NSMutableArray *mutObjects = [[NSMutableArray alloc] initWithCapacity:[mutObjectIds count]];
            for (NSManagedObjectID *objectID in mutObjectIds) {
                NSManagedObject *obj = [context objectWithID:objectID];
                [mutObjects addObject:obj];
   //                    NSLog(@"BG fg===== ");

            }

            if (completion) {
                NSArray *objects = [mutObjects copy];
                completion(objects, nil);
            }
        } else {
            if (completion) {
                completion(nil, error);
            }
        }
    }];
}];
}
我在服务器中有一些记录,当后台到前台时,应用服务器将发送所有记录,并且从客户端我将所有数据保存到coredata中。在保存时,我需要检查这些数据是否已经存在,有时我需要在保存之前从数据库中获取一些数据,但在这段时间里,我的应用程序被冻结,只有在所有更新和保存完成后,它才能正常工作

探查器跟踪

保存到数据库

websocket//连续从服务器获取数据

 - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message
  {
           NSDictionary *responseDict = [message JSONValue];
     NSArray *bodyDicta=[responseDict objectForKey:@"body"];
                for (int i=0; i<bodyDicta.count; i++) {
                    int responseCode=[[[[responseDict objectForKey:@"body"] objectAtIndex:i ] objectForKey:@"code"] intValue];


                    [self checkResponseCode:[bodyDicta objectAtIndex: i] indexvalue:responseCode isArray:1];
 }
UpdatePollWithyncDetails

使用SyncDetails更新Solicitation


你有你的代码行

backgroundContext.persistentStoreCoordinator = coordinator;
…在街区内


在开始performBlock之前,请尝试为MOC设置PSC。

您有自己的代码行

backgroundContext.persistentStoreCoordinator = coordinator;
…在街区内


在开始执行performBlock之前,请尝试为MOC设置PSC。

首先,您如何知道是提取阻塞了您的UI?你用过这个仪器吗?如果是,追踪在哪里

如果没有,则需要停止,运行仪器,使用时间分析器并找到块。使用跟踪链接更新您的问题,以便下载和查看

不看仪器中的这个问题,你只是在猜测实际问题是什么

更新1 查看您提供的跟踪,我没有看到核心数据在主线程或任何其他线程上占用任何大量时间。我怀疑你在这里追错东西了

上面的代码不会为您节省任何时间。虽然它会将对象加载到NSPersistentStoreCoordinator中,使主NSManagedObjectContext获取对象的速度稍快一些,但这并不重要。根据您的时间跟踪,您没有在主线程上花费SQL 132ms total中的任何时间

即使SQL调用花费了大量时间,它仍然会阻塞主线程,因为在执行获取时锁定了NSPersistentStoreCoordinator

根据您提供的跟踪,您的问题在UI中。大部分时间都花在-[IXInBoxViewController tableView;heightForRowAtIndexPath:]上,这是锁定UI的常用位置。深入您的个人资料,找到昂贵的物品并修复它

问题不在于核心数据。我建议删除此线程代码添加线程不是一个性能解决方案,请返回使用NSFetchedResultsController和UITableViewController,然后分析UI代码并修复缓慢的代码

更新2 我从服务器获取大量数据,并不断节省核心数据。我使用的是NSFetchedResultsController,因此对于每个节省,必须重新加载tableview。现在,我试图同时保存少量数据,这是处理大量核心数据保存请求的正确方法吗

您没有提供任何加载数据或保存数据的代码,因此我无法权威地谈论您是否正确地完成了这些部分

加载的数据量并不重要,只要它加载在后台线程的后台上下文中,我更喜欢使用NSOperation子类并保存到核心数据中。NSFetchedResultsController将执行正确的操作,除非同时显示数据,否则对UI的影响将最小。如果数据正在加载到NSFetchedResultsController中,并且相对脱离屏幕,则不会对性能产生重大影响

运行仪器。当性能成为问题时,这是您的第一步

如果数据加载缓慢,请隔离缓慢的行并对其进行寻址

如果你的保存速度慢,那么就把它分成小块


但首先要分析它。否则,您就是在黑暗中拍摄,只是猜测。

首先,您如何知道是抓取阻塞了您的UI?你用过这个仪器吗?如果是,追踪在哪里

如果没有,则需要停止,运行仪器,使用时间分析器并找到块。使用跟踪链接更新您的问题,以便下载和查看

不看仪器中的这个问题,你只是在猜测实际问题是什么

更新1 查看您提供的跟踪,我没有看到核心数据在主线程或任何其他线程上占用任何大量时间。我怀疑你在这里追错东西了

上面的代码不会为您节省任何时间。虽然它会将对象加载到NSPersistentStoreCoordinator中,使主NSManagedObjectContext获取对象的速度稍快一些,但这并不重要。根据你的时间轨迹,你不是 在主线程上花费SQL 132ms总计的任何时间

即使SQL调用花费了大量时间,它仍然会阻塞主线程,因为在执行获取时锁定了NSPersistentStoreCoordinator

根据您提供的跟踪,您的问题在UI中。大部分时间都花在-[IXInBoxViewController tableView;heightForRowAtIndexPath:]上,这是锁定UI的常用位置。深入您的个人资料,找到昂贵的物品并修复它

问题不在于核心数据。我建议删除此线程代码添加线程不是一个性能解决方案,请返回使用NSFetchedResultsController和UITableViewController,然后分析UI代码并修复缓慢的代码

更新2 我从服务器获取大量数据,并不断节省核心数据。我使用的是NSFetchedResultsController,因此对于每个节省,必须重新加载tableview。现在,我试图同时保存少量数据,这是处理大量核心数据保存请求的正确方法吗

您没有提供任何加载数据或保存数据的代码,因此我无法权威地谈论您是否正确地完成了这些部分

加载的数据量并不重要,只要它加载在后台线程的后台上下文中,我更喜欢使用NSOperation子类并保存到核心数据中。NSFetchedResultsController将执行正确的操作,除非同时显示数据,否则对UI的影响将最小。如果数据正在加载到NSFetchedResultsController中,并且相对脱离屏幕,则不会对性能产生重大影响

运行仪器。当性能成为问题时,这是您的第一步

如果数据加载缓慢,请隔离缓慢的行并对其进行寻址

如果你的保存速度慢,那么就把它分成小块



但首先要分析它。否则,您只能在黑暗中进行猜测。

使用xCode调试器,您可以在块内添加断点,并检查它们在哪个线程中执行。是的,它们正在执行,我已经记录了值。我的代码有什么问题吗?使用xCode调试器,您可以在块内添加断点,并检查它们在哪个线程中执行。是的,它们正在执行,我已经记录了值。我的代码有什么问题吗?实际上这是在后台线程中完成的,那么为什么主线程会阻塞呢?我很困惑。你有什么解决办法吗?抱歉之前没有注意到这一点,但是你的背景内容的performBlock方法中包含了你的主要上下文。这将阻止您的UII通过引用获取此方法。我的问题是抓取块我的UI,这就是为什么我使用后台抓取,我不知道是否有其他方法。你能帮助我吗?这一点真的被卡住了。实际上这个抓取是在后台线程中完成的,那么为什么主线程会阻塞呢?我很困惑。你有什么解决办法吗?抱歉之前没有注意到这一点,但是你的背景内容的performBlock方法中包含了你的主要上下文。这将阻止您的UII通过引用获取此方法。我的问题是抓取块我的UI,这就是为什么我使用后台抓取,我不知道是否有其他方法。你能帮助我吗?好的,先生,但是我通过评论那些需要保存和获取coredata的方法发现了这个问题。在那之后,它工作得很好,先生,我已经用确切的问题更新了我的问题。好的,先生,我将尝试修复UI问题。我从服务器获取大量数据,并不断节省核心数据。我使用的是NSFetchedResultsController,因此对于每个节省,必须重新加载tableview。现在我正在尝试同时保存少量数据,这是处理大量核心数据保存请求的正确方法吗?请将其转移到一个单独的问题中并关闭此问题。好的,先生,我打开了另一个链接好的,先生,但我通过评论那些需要保存和获取核心数据的方法发现了这个问题。在那之后,它工作得很好,先生,我已经用确切的问题更新了我的问题。好的,先生,我将尝试修复UI问题。我从服务器获取大量数据,并不断节省核心数据。我使用的是NSFetchedResultsController,因此对于每个节省,必须重新加载tableview。现在我正在尝试同时保存少量数据,这是处理大量核心数据保存请求的正确方法吗?请将其转移到另一个问题并关闭此问题。好的,先生,我打开了另一个链接
-(void)updatePollWithSyncDetails:(NSDictionary *)responseDict
 {
     BOOL isDuplicate=[[IXDataBaseManager sharedNetworkDataManager] checkForExistenceOfThreadDetailsForThreadID:[responseDict objectForKey:@"poll"]];
if(!isDuplicate)
{
             [[IXDataBaseManager sharedNetworkDataManager] updateThreadEntityWithSyncDetails:detailsDict];
 }
 -(void)updateSolicitationWithSyncDetails:(NSDictionary *)inDictionary
 {
 NSMutableDictionary *paramDict=[NSMutableDictionary dictionaryWithDictionary:inDictionary];
 NSString *userEmail=[[NSUserDefaults standardUserDefaults] valueForKey:@"currentUser"];
[paramDict setObject:[NSNumber numberWithBool:NO] forKey:@"isSystemMessage"];                          
                [paramDict setObject:message forKey:@"threadDescription"];
                ThreadInfo *threadInfo=[[IXDataBaseManager sharedNetworkDataManager] retrieveSolicitationInfoForThreadID:[inDictionary objectForKey:@"solicitation"]];
                [paramDict setObject:threadInfo.threadID forKey:@"thread"];
                [[IXDataBaseManager sharedNetworkDataManager] updateThreadEntityWithSyncDetails:paramDict];
            }
        }
 }
backgroundContext.persistentStoreCoordinator = coordinator;