我将表与自定义UITableViewCell分组。我正在使用AFNetworking调用Web服务并将它们存储在Core Data Entity中。我使用NSFetchedResultsViewController显示Core Data表中的数据。我也搜索了tableview。出于某种原因,即使核心数据实体中存在数据,NSFetchedResultsController
也不会返回任何数据。你能帮忙解决这个问题吗?这是我的代码。
#import "MasterViewController.h"
#import "DetailViewController.h"
@interface MasterViewController ()
@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
@end
@implementation MasterViewController
@synthesize fetchedResultsController;
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
}
-(void)viewDidAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"RackStatusViewLoaded" object:self];
self.navigationItem.title = [defaults objectForKey:@"loggedInUserSelectedStoreName"];
NSString *activeStockTakeRequestPath = [NSString stringWithFormat:@"%@/stocktake/store/%@/activestocktake",[appDelegate baseUrl],[defaults objectForKey:@"loggedInUserSelectedStoreId"]];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:[appDelegate baseUrl]]];
NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
path:activeStockTakeRequestPath
parameters:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSInteger statusCode = operation.response.statusCode;
// NSLog(@"AFNetowrking Response: %@", [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
NSLog(@"AF Status Code %d",statusCode);
NSError *error;
NSMutableDictionary *returnedDict = [NSJSONSerialization JSONObjectWithData:responseObject options:kNilOptions error:&error];
if (statusCode==200)
{
NSLog(@"Status 200");
[defaults setBool:true forKey:@"isActiveStockTakeForCurrentStore"];
[defaults setObject:returnedDict[@"id"] forKey:@"ActiveStockTakeid"];
[defaults setObject:returnedDict[@"name"] forKey:@"ActiveStockTakeName"];
[defaults setObject:returnedDict[@"onDate"] forKey:@"ActiveStockTakeDate"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"setTitleForCurrentActiveStock" object:self];
NSLog(@"isActiveStock? %@",[defaults objectForKey:@"isActiveStockTakeForCurrentStore"]);
NSLog(@"ActiveStockTakeid? %@",[defaults objectForKey:@"ActiveStockTakeid"]);
NSLog(@"ActiveStockTakeName? %@",[defaults objectForKey:@"ActiveStockTakeName"]);
NSLog(@"ActiveStockTakeDate? %@",[defaults objectForKey:@"ActiveStockTakeDate"]);
[defaults synchronize];
self.fetchedResultsController = nil;
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"RackStockTakeStatus"];
[self requestLocationDataWithStatus];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
if (error != nil) {
//Deal with failure
}
else {
NSLog(@"Data from Core Data %@", results);
NSLog(@"Count From Core Data Entity : %d",[results count]);
}
[self performFetchForItemsInStore];
[self.tableView reloadData];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}
}];
[operation start];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
appDelegate.selectedRackForTakeStock = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSLog(@"Selected Rack %@",appDelegate.selectedRackForTakeStock);
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[defaults setObject:cell.textLabel.text forKey:@"selectedRackInTakeStock"];
[defaults synchronize];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
NSLog(@"Number of Rows: %d",[sectionInfo numberOfObjects]);
return [sectionInfo numberOfObjects];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSLog(@"Number of Sections: %d",[[self.fetchedResultsController sections] count]);
return [[self.fetchedResultsController sections] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = @"takeStockCell";
UITableViewCell * cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
RackStockTakeStatus *rackStockTakeStatus = [self.fetchedResultsController objectAtIndexPath:indexPath];
UILabel *rackName, *status, *user, *progress;
rackName = (UILabel *)[cell viewWithTag:1];
rackName.text = rackStockTakeStatus.locName;
status = (UILabel *)[cell viewWithTag:2];
status.text = rackStockTakeStatus.status;
status.text = rackStockTakeStatus.status;
progress = (UILabel *)[cell viewWithTag:3];
if (rackStockTakeStatus.percentCompleted!=nil)
{
progress.text = [NSString stringWithFormat:@"Progress: %@%%",rackStockTakeStatus.percentCompleted];
}
if (rackStockTakeStatus.stockTakeByUser!=nil)
{
user = (UILabel *)[cell viewWithTag:4];
user.text = rackStockTakeStatus.stockTakeByUser;
}
}
- (void)requestLocationDataWithStatus {
NSLog(@"Entering requestDataItemsForStore");
NSString *requestPath = [NSString stringWithFormat:@"/stocktake/stocktake/%@/usr/1/locwithstatus",[defaults objectForKey:@"loggedInUserSelectedStoreId"]];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:[appDelegate baseUrl]]];
NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
path:requestPath
parameters:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSInteger statusCode = operation.response.statusCode;
// NSLog(@"AFNetowrking Response: %@", [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
NSLog(@"AF Status Code %d",statusCode);
NSError *error;
NSMutableDictionary *returnedDict = [NSJSONSerialization JSONObjectWithData:responseObject options:kNilOptions error:&error];
if (statusCode==200)
{
for (NSDictionary *rackStockTakeStatus in returnedDict) {
RackStockTakeStatus *rackStockTakeStatusObj;
rackStockTakeStatusObj.stockTakeLocId = rackStockTakeStatus[@"stockTakeLocId"];
rackStockTakeStatusObj.stockTakeUuid = rackStockTakeStatus[@"stockTakeUuid"];
rackStockTakeStatusObj.locId = rackStockTakeStatus[@"locId"];
rackStockTakeStatusObj.locName = rackStockTakeStatus[@"locName"];
rackStockTakeStatusObj.status = rackStockTakeStatus[@"status"];
rackStockTakeStatusObj.stockTakeByUser = rackStockTakeStatus[@"stockTakeByUser"];
rackStockTakeStatusObj.stockTakeByUserId = rackStockTakeStatus[@"stockTakeByUserId"];
rackStockTakeStatusObj.beginTime = rackStockTakeStatus[@"beginTime"];
[self saveDataToCoreDataEntity:rackStockTakeStatusObj];
}
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
[operation start];
}
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"RackStockTakeStatus" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *rackNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"locName" ascending:YES];
NSArray *sortDescriptors = @[rackNameDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
fetchedResultsController.delegate = self;
return fetchedResultsController;
}
- (void)fetchItemsForStore {
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"RackStockTakeStatus" inManagedObjectContext:context];
[request setEntity:entity];
NSError *error;
[context executeFetchRequest:request error:&error];
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"Begin Updates");
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"End Updates");
[self.tableView endUpdates];
}
-(void)performFetchForItemsInStore
{
NSLog(@"Entering performFetchForItemsInStore");
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
}
}
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSLog(@"Cancelled - searchDisplayControllerDidEndSearch");
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"RackStockTakeStatus" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *rackNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"locName" ascending:YES];
NSArray *sortDescriptors = @[rackNameDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
fetchedResultsController.delegate = self;
[self performFetchForItemsInStore];
[self.tableView reloadData];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
NSInteger searchOption = controller.searchBar.selectedScopeButtonIndex;
return [self searchDisplayController:controller shouldReloadTableForSearchString:searchString searchScope:searchOption];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
NSString * searchString = controller.searchBar.text;
return [self searchDisplayController:controller shouldReloadTableForSearchString:searchString searchScope:searchOption];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString*)searchString searchScope:(NSInteger)searchOption {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"locName contains[cd] %@", searchString];
[self.fetchedResultsController.fetchRequest setPredicate:predicate];
[self.fetchedResultsController.fetchRequest setFetchLimit:100];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
TODO: "Error Handling / Error message";
}
return YES;
}
-(void)saveDataToCoreDataEntity:(RackStockTakeStatus *) rackStockTakeStatus
{
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *rackStockTakeStatusManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"RackStockTakeStatus" inManagedObjectContext:context];
[rackStockTakeStatusManagedObject setValue:rackStockTakeStatus.stockTakeLocId forKey:@"stockTakeLocId"];
[rackStockTakeStatusManagedObject setValue:rackStockTakeStatus.stockTakeUuid forKey:@"stockTakeUuid"];
[rackStockTakeStatusManagedObject setValue:rackStockTakeStatus.locId forKey:@"locId"];
[rackStockTakeStatusManagedObject setValue:rackStockTakeStatus.locName forKey:@"locName"];
[rackStockTakeStatusManagedObject setValue:rackStockTakeStatus.status forKey:@"status"];
[rackStockTakeStatusManagedObject setValue:rackStockTakeStatus.stockTakeByUser forKey:@"stockTakeByUser"];
[rackStockTakeStatusManagedObject setValue:rackStockTakeStatus.stockTakeByUserId forKey:@"stockTakeByUserId"];
[rackStockTakeStatusManagedObject setValue:rackStockTakeStatus.beginTime forKey:@"beginTime"];
[rackStockTakeStatusManagedObject setValue:rackStockTakeStatus.percentCompleted forKey:@"percentCompleted"];
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Save Failed for Data %@! %@ %@", rackStockTakeStatus, error, [error localizedDescription]);
}
}
答案 0 :(得分:0)
当您收到回复时,会在其中填写未初始化的CoreData对象。
if (statusCode==200)
{
for (NSDictionary *rackStockTakeStatus in returnedDict) {
RackStockTakeStatus *rackStockTakeStatusObj; // !!! MISSING INITIALIZATION HERE
rackStockTakeStatusObj.stockTakeLocId = rackStockTakeStatus[@"stockTakeLocId"];
当你填充它时,它可以指向任何内存。
这种情况的常见做法是为其ID获取已存在的CoreData对象。如果此ID不存在任何对象,则应创建新对象。 在用数据填充后,控制器将获取结果。
if (statusCode==200)
{
for (NSDictionary *rackStockTakeStatus in returnedDict) {
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"RackStockTakeStatus"];
request.fetchLimit = 1;
request.predicate = [NSPredicate predicateWithFormat:@"stockTakeLocId = %@", rackStockTakeStatus[@"stockTakeLocId"]];
NSError *error = nil;
RackStockTakeStatus *rackStockTakeStatusObj = [[context executeFetchRequest:request error:&error] firstObject];
if (nil == rackStockTakeStatusObj)
{
rackStockTakeStatusObj = [NSEntityDescription insertNewObjectForEntityForName:@"RackStockTakeStatus" inManagedObjectContext:context]
rackStockTakeStatusObj.stockTakeLocId = rackStockTakeStatus[@"stockTakeLocId"];
}
...