Ios 应用程序滞后于通过RestKit&;神奇记录

Ios 应用程序滞后于通过RestKit&;神奇记录,ios,multithreading,core-data,restkit,Ios,Multithreading,Core Data,Restkit,我想知道是什么加载了UI线程。在类(UITableView的子类)中有一个FRC: NSFetchRequest *request = [DEPlace MR_requestAllWithPredicate:[NSPredicate predicateWithFormat:@"isWorking == YES"]]; request.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:

我想知道是什么加载了UI线程。在类(UITableView的子类)中有一个FRC:

 NSFetchRequest *request = [DEPlace MR_requestAllWithPredicate:[NSPredicate predicateWithFormat:@"isWorking == YES"]];

 request.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES] ];
 self.placesController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                managedObjectContext:[NSManagedObjectContext MR_rootSavingContext]
                                                                  sectionNameKeyPath:nil
                                                                           cacheName:nil];
 self.placesController.delegate = self;
它以前被附加到MR_contextforcurrent线程。将其更改为rootSavingContext会略微影响性能。然后我将根上下文和默认上下文设置为同一个:

[NSManagedObjectContext MR_setRootSavingContext:managedObjectStore.persistentStoreManagedObjectContext];
[NSManagedObjectContext MR_setDefaultContext:managedObjectStore.persistentStoreManagedObjectContext];
用于设置为mainQueueManagedObjectContext的默认上下文。我想移动所有与后台相关的核心数据,让FRC负责和UI的交互。FRC委托通过以下方式获取新数据:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
  //self.places = [self sortPlaces:controller.fetchedObjects];

  self.places = controller.fetchedObjects;

  [self.delegate contentUpdatedInDatasource:self];
} 
我现在禁用了排序功能,认为这可能会影响主线程。我试着找出还有什么可以用时间分析器加载主线程,但没有发现任何可疑的东西

当所有的数据都加载后,一切都顺利运行,应用程序只会在第一次启动时,即数据库被填充时滞后。由于与加载相关的所有内容都由RestKit持有,我认为这不会导致问题

我曾考虑将请求最多延迟10秒,但不知道如何才能实现。基本上,在开始的时候,应用程序会获得一个ID数组(现在大约250个),然后通过该数组循环,并根据每个ID从服务器请求数据。到目前为止,这还不是很关键,但当数组增长到1-2k时,这将是一个大问题。顺便说一句,一个数据对象在数据库中有4个关系。减少依赖性是可能的解决方案吗

更新: 我试图将请求拆分为1乘1,这导致了一种非常奇怪的行为。 由于某些原因,请求之间存在巨大的延迟。 这就是我获取ID数组的方式

        AFJSONRequestOperation *op = [[AFJSONRequestOperation alloc] initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[APIRoot stringByAppendingFormat:@"/venues/listId?%@=%@&%@=%@", TokenKey, [DEUser token], UDIDKey, [DEUser udid]]]]];

        // dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
        dispatch_queue_t backgroundQueue = dispatch_queue_create("com.name.bgqueue", NULL);
        op.successCallbackQueue = backgroundQueue;

        [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
             //gettin an array of IDs
            NSArray *array = (NSArray*) responseObject;
            if(array.count)
            {
                _array = array;
                [self getVenuesFromSelfArrayWithCurrentIndex:0];
            }
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"3rr0r: %@", error);
        }];

        [[NSOperationQueue mainQueue] addOperation:op];
这是一个递归方法的代码:

- (void)getVenuesFromSelfArrayWithCurrentIndex: (NSUInteger)index
{
if(index >= _array.count){ NSLog(@"loading finished!"); return; }
//version of the app, location e.t.c.
NSMutableDictionary *options = [[self options] mutableCopy];
[options setObject:[_array objectAtIndex:index] forKey:@"venueId"];
//method below calls RKs getObjectsAtPath, and it's pretty much the only thing it does
[[DEAPIService sharedInstance] getObjectsOfClass:[DEPlace class]
                                     withOptions:options
                                         success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult){
                                             NSManagedObject *object = [mappingResult.array firstObject];
                                             if([object isKindOfClass:[DEPlace class]])
                                             {
                                                 [self getVenuesFromSelfArrayWithCurrentIndex:index+1];
                                             }
                                         } failure:^(RKObjectRequestOperation *operation, NSError *error){
                                            NSLog(@"Failed to load the place with options: %@", options.description);
                                             [self getVenuesFromSelfArrayWithCurrentIndex:index+1];
                                         }];
}
奇怪的是,启动下一个请求需要约1-2秒(!)的时间,cpu使用日志和线程外观。。奇怪


有什么建议吗?

目前,我只能提出大约250个请求。在移动设备上,如果不使网络泛滥并使其停止,您不能发出超过4或5个并发网络请求。实际上,您应该更改web服务设计,以便可以发送批处理请求,因为这对客户端和服务器都非常有效


无论如何,您可以通过设置对象管理器的
operationQueue
maxConcurrentOperationCount
来限制并发请求。建议将其设置为4。

FRC应始终附加到主线程上下文-它由UI使用,因此它不能使用背景上下文(至少不常见)。那么您在启动时同时发出250个请求?因为我将它附加到了rootSavingContext,所以我猜它现在附加到了persistentStoreManagedObjectContext。正确,我收到250个启动请求。有时应用程序只是锁定(我以为它不见了,但我错了)。我的单个请求是~10-15Kb。Ofc我可以把请求分成小组等等,但我真的需要了解是什么导致了这些延迟。当我调用RK的getObjectsAtPath时,它会创建RKRequestOperation吗?其他246个请求会被放入队列吗?是的,它为请求和其他映射创建操作。250个网络请求并不理想;-)那么,我应该考虑减少请求量吗?我在考虑做一些递归来逐个执行请求。最好通过批处理来减少请求数量。设置和拆除连接的成本很高,所以如果是后台类型的操作,而不是时间敏感的操作,那么最好在每个请求中添加更多内容。我自己做了一些“错误的批处理”,并更新了原始帖子。我去检查RK的分页器。