NSOperationQueueとNSInvocationOperationを使用してUIViewControllerのメソッドを呼び出し、UIViewControllerが別のクラスのメソッドを呼び出して、WebからXMLファイルを解析し、いくつかのCoreData管理対象オブジェクトを更新しています。
このプロセスは、最初にアプリケーションを実行したときに機能しますが、2回目にメソッドを呼び出すと(UIViewControllerが再度表示されたとき)、XMLパーサークラスのexecuteFetchRequestステートメントの後に行が実行されません。実行に使用しているコードは次のとおりです。
ロード時にCoreDataストアから駐車場のすべての静的情報を取得する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から取得して解析し、CoreDataストアで使用可能なスペースを更新しようとします。
-(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
}
}
管理対象オブジェクトコンテキストの使用方法に問題がありますか?
助けてくれてありがとう