2015-11-07 40 views
0

我已經爲自定義的UITableViewCell分組了表。我正在使用AFNetworking調用Web服務並將它們存儲在Core Data Entity中。我使用NSFetchedResultsViewController顯示核心數據表中的數據。我也有在桌面上搜索。由於某些原因,即使Core Data Entity中存在數據,NSFetchedResultsController也不會返回任何數據。你能幫助解決這個問題嗎?這是我的代碼。即使核心數據實體有數據,FetchedResultsController也會返回空

#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

當您收到任何答覆,則用它填充未初始化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"]; 
       } 
       ... 
+0

我創建rackStockTakeStatusObj只是爲了將它傳遞給幫助保存數據到核心數據實體的函數。數據正確保存到核心數據實體。問題在於fetchedresultscontroller。這很重要嗎? – saif

+0

我看不到你創建它。正如我指定你只是聲明它。然後你進一步創建一個新的對象,並用來自非初始化對象的數據填充它。 – DisableR

+0

此外,您正在創建每個新對象,而不檢查是否已經爲此類stockTakeLocId保存對象。 – DisableR

相關問題