Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 后台线程上的核心数据提取请求仅用于第一次提取_Ios_Xcode_Core Data_Nsmanagedobject_Nsoperationqueue - Fatal编程技术网

Ios 后台线程上的核心数据提取请求仅用于第一次提取

Ios 后台线程上的核心数据提取请求仅用于第一次提取,ios,xcode,core-data,nsmanagedobject,nsoperationqueue,Ios,Xcode,Core Data,Nsmanagedobject,Nsoperationqueue,我正在使用NSOperationQueue&NSInvocationOperation调用UIViewController上的一个方法,然后调用另一个类中的一个方法,该类从web解析XML文件并更新一些核心数据管理对象 当我第一次运行应用程序时,这个过程可以工作,但是当我第二次调用该方法时(当再次显示UIViewController时),它不会在XML解析器类中的executeFetchRequest语句之后执行任何行。下面是我用来执行的代码: 我有一个UITableViewController

我正在使用NSOperationQueue&NSInvocationOperation调用UIViewController上的一个方法,然后调用另一个类中的一个方法,该类从web解析XML文件并更新一些核心数据管理对象

当我第一次运行应用程序时,这个过程可以工作,但是当我第二次调用该方法时(当再次显示UIViewController时),它不会在XML解析器类中的executeFetchRequest语句之后执行任何行。下面是我用来执行的代码:

我有一个UITableViewController,它在加载时从我的核心数据存储中获取停车场的所有静态信息:

- (void)viewDidLoad
{
    NSLog(@"viewDidLoad");
    [super viewDidLoad];

    southeastCarparks = [[NSMutableArray alloc] init];
    southwestCarparks = [[NSMutableArray alloc] init];
    northeastCarparks = [[NSMutableArray alloc] init];
    northwestCarparks = [[NSMutableArray alloc] init];
    carparkLocations = [[NSMutableArray alloc] initWithObjects:southeastCarparks, southwestCarparks, northeastCarparks, northwestCarparks, nil];


    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                               entityForName:@"CarparkInfo" inManagedObjectContext:self.managedObjectContext];


    [fetchRequest setEntity:entity];
    NSError *error;
    self.carparkInfos = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

    for (CarparkInfo *carpark in self.carparkInfos){
        if ([carpark.details.region isEqualToString:@"Southeast"]){
            [southeastCarparks addObject:carpark];
        } else if ([carpark.details.region isEqualToString:@"Southwest"]){
            [southwestCarparks addObject:carpark];
        } else if ([carpark.details.region isEqualToString:@"Northeast"]){
            [northeastCarparks addObject:carpark];
        } else if ([carpark.details.region isEqualToString:@"Northwest"]){
            [northwestCarparks addObject:carpark];
        }
    }

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(loadXMLData)
                                             name:@"appDidBecomeActive"
                                           object:nil];
}
然后,当视图出现时,我调用loadXML方法转到web并从xml文件中获取最新的停车位信息

- (void) viewDidAppear:(BOOL)animated
{
    [self loadXMLData];
    NSLog(@"viewDidAppear");
}


- (void) loadXMLData {
    NSLog(@"loadXMLData");

    NSOperationQueue *queue = [NSOperationQueue new];
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
                                                        selector:@selector(loadXMLDataWithOperation)
                                                                          object:nil];
    [queue addOperation:operation];
}

- (void) loadXMLDataWithOperation {
    xmlParser = [[XMLParser alloc] loadXMLByURL:xmlFileURL];

    [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
}
在XMLParser类中,我获取传入的xmlFileURL,从web检索它,解析它,然后尝试更新核心数据存储中的可用空间

-(id) loadXMLByURL:(NSString *)urlString
{
    _carparks = [[NSMutableArray alloc] init];
    NSURL *url = [NSURL URLWithString:urlString];
    NSData *data = [[NSData alloc] initWithContentsOfURL:url];
    parser = [[NSXMLParser alloc] initWithData:data];
    parser.delegate = self;
    [parser parse];
    return self;
}

- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
    if (![elementName isEqualToString:@"carpark"]){
        return;
    }

    currentCarpark = [Carpark alloc];

    NSString *name = [attributeDict objectForKey:@"name"];
    currentCarpark.name = name;

    NSString *spaces = [attributeDict objectForKey:@"spaces"];
    currentCarpark.spaces = spaces;

    [self.carparks addObject:currentCarpark];
    currentCarpark = nil; 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    // set up the managedObjectContext to read data from CoreData
    id delegate = [[UIApplication sharedApplication] delegate];
    self.managedObjectContext = [delegate managedObjectContext];

    NSEntityDescription *entity = [NSEntityDescription
                               entityForName:@"CarparkInfo" inManagedObjectContext:self.managedObjectContext];

    [fetchRequest setEntity:entity];
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"code=%@",name]];

    NSError *error;
    CarparkInfo *cgCarpark;

    // THIS IS THE LAST LINE TO BE EXECUTED THE 2ND TIME AROUND. THE APPLICATION DOESN'T THROW AN ERROR BUT DOESN'T GO ON TO UPDATE THE CARPARK OBJECT ON THE LINE AFTER
    cgCarpark = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] lastObject];

    cgCarpark.availableSpaces = spaces;
    error = nil;
    if (![self.managedObjectContext save:&error]) {
        //Handle any error with the saving of the context
    }
}
我使用托管对象上下文的方式是否有问题


提前感谢您的帮助

在获取结果控制器之前,只需编写以下语句

self.fetchedResultsController = nil;

在获取结果控制器之前,只需编写以下语句

self.fetchedResultsController = nil;

我认为@Mark_Kryzhanouski是正确的,你陷入了僵局。可能是因为您正在多个线程上访问
NSManagedObjectContext
。您需要小心处理
核心数据中的线程。您的
NSOperation
将在后台线程上运行,因此对
NSManagedObjectContext
的调用将不会与
viewDidLoad
中的第一个调用在同一线程上。下面是一些有关
核心数据
并发性的参考资料


WWDC 2012年的视频“第214次会议-核心数据最佳实践”中也有一个很好的WWDC演示。我认为@Mark_Kryzhanouski是正确的,您遇到了僵局。可能是因为您正在多个线程上访问
NSManagedObjectContext
。您需要小心处理
核心数据中的线程。您的
NSOperation
将在后台线程上运行,因此对
NSManagedObjectContext
的调用将不会与
viewDidLoad
中的第一个调用在同一线程上。下面是一些有关
核心数据
并发性的参考资料


在WWDC 2012视频“会话214-核心数据最佳实践”中,也有一个很好的WWDC演示。我想您需要展示如何调用这段代码。这一行似乎出现了死锁。请给我们一个运行此方法的上下文。我已经更新了代码以显示如何调用此方法。有没有办法检查是否发生死锁?我添加了日志记录,并注意到在视图启动时loadXMLData被调用了两次:一次是通过添加NSNotification,另一次是在ViewDidDisplay中调用,因此,我需要找出一种替代方法来在viewDidLoad中创建NSNotification。我认为您需要展示如何调用这段代码。这一行中似乎出现了死锁。请给我们一个运行此方法的上下文。我已经更新了代码以显示如何调用此方法。有没有办法检查是否发生死锁?我添加了日志记录,并注意到在视图启动时loadXMLData被调用了两次:一次是通过添加NSNotification,另一次是在ViewDidDisplay中调用,因此,我需要找出在viewDidLoad中创建NSNotification的替代方法。我不确定您建议我在何处插入此语句。我不会将FetchedResultsController传递给解析XML和更新核心日期对象的类。我正在将该类的ManagedObjectContext设置为在AppDelegate中创建的ManagedObjectContext。我不确定您建议我在何处插入此语句。我不会将FetchedResultsController传递给解析XML和更新核心日期对象的类。我正在将该类的ManagedObjectContext设置为在AppDelegate中创建的ManagedObjectContext。我在后台线程上创建了一个单独的NSManagedObjectContext,并将其指向应用程序的persistentStoreCoordinator。然后在主线程中,我添加了一个通知以侦听NSManagedObjectContextDidSaveNotification调用,并在主线程的NSManagedObjectContext上调用了mergeChangesFromContextDidSaveNotification。不确定这是否是理想的解决方案,但现在似乎效果更好。感谢您的帮助。我在后台线程上创建了一个单独的NSManagedObjectContext,并将其指向应用程序的persistentStoreCoordinator。然后在主线程中,我添加了一个通知以侦听NSManagedObjectContextDidSaveNotification调用,并在主线程的NSManagedObjectContext上调用了mergeChangesFromContextDidSaveNotification。不确定这是否是理想的解决方案,但现在似乎效果更好。谢谢你的帮助。