TableView not displaying Cell Content - ios

I am Using core data as my data base. Inside my UITableView I have a button to add projects , But at this moment I only Use it to add names. But the names I add do not display on the tableview.
I think my problem is that I need to repopulate my projectArray, how and where do I do that.
Here is my code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_projectArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Project* project = _projectArray[indexPath.row];
static NSString *cellID = #"TableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
cell.textLabel.text = project.name;
cell.detailTextLabel.text = #"prooo";
self.tableView.delegate = self;
self.tableView.dataSource = self;
return cell;
}
Here is my button code:
- (IBAction)addProjectButton:(id)sender {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Enter new project name."
message:nil
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
UITextField *textField = [alert textFieldAtIndex:0];
textField.placeholder = #"Project Name";
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex != alertView.cancelButtonIndex) {
UITextField *field = [alertView textFieldAtIndex:0];
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [delegate managedObjectContext];
NSManagedObject *object =[NSEntityDescription insertNewObjectForEntityForName:#"Project" inManagedObjectContext:context];
[object setValue:field.text forKey:#"name"];
NSError *error;
[context save:&error];
if (![context save:&error]) {
NSLog(#"Whoops %# %#", error, [error localizedDescription]);
}
[self.tableView reloadData];
} else {
NSLog(#"cancel");
}
}
And here is my ViewWillAppear Code , where I fetch info:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:nil];
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [delegate managedObjectContext];
//load project
NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
[fetch setEntity:entity];
NSError *error;
_projectArray = [context executeFetchRequest:fetch error:&error];
}

There are many things you can do. To make it a good code, I will suggest write a method that reloads your array. Like this
-(void) reloadArray
{
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [delegate managedObjectContext];
//load project
NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
[fetch setEntity:entity];
NSError *error;
_projectArray = [context executeFetchRequest:fetch error:&error];
}
Then replace your viewDidAppear like this -
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:nil];
[self reloadArray];
}
Also in your numberOfSectionsInTableView: method, make this change -
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
[self reloadArray];
return 1;
}
And it should do the magic...

Have you set the dataSource and delegate properties of tableView?
self.tableView.delegate = self;
self.tableView.dataSource = self;

Change This :
NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
[fetch setEntity:entity];
NSError *error;
_projectArray = [context executeFetchRequest:fetch error:&error];
To:
_projectArray = [[NSMutableArray alloc]init];
NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
[fetch setEntity:entity];
NSManagedObject *object = nil;
NSError *error;
NSArray *result = [context executeFetchRequest:fetch error:&error];
for (int i = 0; i < [result count]; i ++) {
object = [result objectAtIndex:i];
[_projectArray setObject:[object valueForKey:#"name"]
}

Related

Core Data: NSManagedObjects stored in array turn into nil when scrolling in table view

I have some NSManagedObjects that I am retrieving and storing in an array for populating a table view. When the view first loads, all of the data is there, but when I scroll the NSManagedObjects in the array turn to nil.
I fetch like this in viewDidLoad:
AppDelegate *appDelegate = [[AppDelegate alloc] init];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Tracks" inManagedObjectContext:appDelegate.managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [appDelegate.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(#"An Error! %#",error);
}
mutArray = [[NSMutableArray alloc] initWithArray:fetchedObjects];
My NSManagedObject subclass is named "Tracks". When the view loads, I can assign a Tracks object from mutArray, but when I scroll the Tracks object is always nil. Here is my cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"TracksCell";
TracksCell *cell = (TracksCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TracksCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
Tracks *track = [mutArray objectAtIndex:indexPath.row];
cell.titleLabel.text = track.name;
cell.addressLabel.text = [NSString stringWithFormat:#"%#, %#",track.city,track.state];
return cell;
}
So just to be clear, this works when the table first loads. But if I scroll down then back up the Tracks object on the first row is nil. Also any rows that haven't been loaded (below the view) are nil when I scroll down.
What am I missing here?
So thanks to #JanGreve posting the documentation in the comments, heres the answer for anyone needing some help setting up NSFetchedResultsController.
in your .h file:
add <NSFetchedResultsControllerDelegate>
and add property:
#property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
in your .m file:
#synthesize fetchedResultsController = _fetchedResultsController;
viewDidLoad:
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Error! %#",error);
abort();
}
add this method to populate your fetchedResultsController:
#pragma mark -
#pragma mark Fetched Results Controller section
-(NSFetchedResultsController *) fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
AppDelegate *appDelegate = [[AppDelegate alloc] init];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Tracks" inManagedObjectContext:appDelegate.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
_fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
then in my cellForRowAtIndexPath: get your populate your NSManagedObject subclass like this:
Tracks *track = [self.fetchedResultsController objectAtIndexPath:indexPath];

FetchedResultsController returns null even when core data entity has data

I have grouped table with custom UITableViewCell. I am calling a web service using AFNetworking and storing them in Core Data Entity. I display the data from Core Data table by using NSFetchedResultsViewController. I also have search on the tableview. For some reason, NSFetchedResultsController returns no data even though there is a data in the Core Data Entity. Can you help in resolving this issue? here is my code.
#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]);
}
}
When you receive a response, you fill with it a non-initialized CoreData object.
if (statusCode==200)
{
for (NSDictionary *rackStockTakeStatus in returnedDict) {
RackStockTakeStatus *rackStockTakeStatusObj; // !!! MISSING INITIALIZATION HERE
rackStockTakeStatusObj.stockTakeLocId = rackStockTakeStatus[#"stockTakeLocId"];
At the time you fill it it can point on whatever piece of memory.
Common practice for such case is fetching already existing CoreData object for its ID. If no objects exist for such ID, you should create a new object.
After you can fill it with the data and fetched results controller will observe changes.
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"];
}
...

Fetching UIImage from Core Data

I am using a Core Data to save a UIImage that i get from my UIImagePickerController (source type = image library). I then Place or rather want to place the photo in a UICollectionViewCell, Please help and check to see what I am doing wrong.
Here is my UIImagePickerController it is called by a delegate.
-(void)requestAddScreen {
_picker = [[UIImagePickerController alloc] init];
_picker.delegate = self;
_picker.allowsEditing = NO;
_picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:_picker animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [delegate managedObjectContext];
NSEntityDescription* entityDescription = [NSEntityDescription entityForName:#"Screen" inManagedObjectContext:context];
Screen* newScreen = [[Screen alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:context];
NSData *imageData = UIImagePNGRepresentation(image);
newScreen.image = imageData;
[_project addProjectScreensObject:newScreen];
NSError *error;
[context save:&error];
if (![context save:&error]) {
NSLog(#"Whoops %# %#", error, [error localizedDescription]);
}
[self dismissViewControllerAnimated:_picker completion:^{
[_collectionView reloadData];
}];
}
And Here is my ViewWillAppear meted. this is where I fetch the data from Core Data, id it Correct?
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:nil];
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [delegate managedObjectContext];
//load project
NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
[fetch setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", #"EMO-KIT"];
[fetch setPredicate:predicate];
NSError *error;
NSArray *array = [context executeFetchRequest:fetch error:&error];
if (array.count == 1) {
_project = array[0];
} else {
_project = [NSEntityDescription insertNewObjectForEntityForName:#"Project" inManagedObjectContext:context];
[_project setValue:#"EMO-KIT" forKey:#"name"];
}
NSArray* screens = [[_project projectScreens] array];
NSIndexPath *bottomIndexPath=[NSIndexPath indexPathForRow:screens.count inSection:0];
[self.collectionView scrollToItemAtIndexPath: bottomIndexPath atScrollPosition:UICollectionViewScrollPositionRight animated:YES];
}
You can convert UIImage to NSData and save into Core Data as below
Saving
NSData * imageData = UIImagePNGRepresentation(image);
[newsObj setValue:imageData forKey:#"Image"];
Retrieving
UIImage *image = [UIImage imageWithData:[screenObj valueForKey:#"Image"]];
Hope it helps you..

Editing specific CoreData entries

Once again, since Core Data is new to me, I need assistance. Basically, I need to edit a specific Core Data object from a view outside the tableview, save it, and reload the tableview. I can manage reloading the tableview, but I cannot figure out how to find the specific Core Data object for that indexPath entry. I don't have any code because I cannot find anything to suit my purpose.
Detail (Editor)
-(IBAction)cancel:(id)sender{
NSLog(#"Sent!");
// [self dismissViewControllerAnimated:YES completion:nil];
// [self.view.superview removeFromSuperview];
OweDetails *details = info.details;
[info setValue:oField.text forKey:#"name"];
info.name = oField.text;
[UIView animateWithDuration:0.5
delay:1.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
self.master = [[MasterViewController alloc]init];
[self dismissSemiModalViewController:self];
[self.master.tableView reloadData];
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
}
Master (TableView)
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"I tapped myself!");
OweInfo *info = [_fetchedResultsController objectAtIndexPath:indexPath];
self.tdModal = [[TDSemiModalViewController alloc]init];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
FooterViewController *fvc = [[FooterViewController alloc]init];
OweDetails *details = info.details;
[self.tdModal setDetailItem:info.name];
[self.tdModal setMoneyItem:details.money];
// [self.view addSubview:test.view];
self.tdModal.managedObjectContext = self.managedObjectContext;
self.tdModal.managedObjectContext = self.managedObjectContext;
OweInfo *info2 = (OweInfo *)[nameArray objectAtIndex:indexPath.row];
self.tdModal.info = info2;
[self presentSemiModalViewController:self.tdModal];
}
If you're using an NSFetchedResultsController, ask it for the objectAtIndexPath:.
AppDelegate* appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext* context = [appDelegate managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"YOUR_ENTITY_NAME" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SOME_PREDICATE_USED_TO_UNIQUELY_IDENTIFY_YOUR_INDEXPATH ==%#", #"VALUE"];
[fetchRequest setPredicate:predicate];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];
NSError* error;
NSArray* array = [context executeFetchRequest:request error:&error];
if (error)
{
NSLog(#"Error fetching data. %#", error);
return nil;
}
if (array.count != 1)
{
NSLog(#"Invalid number (%d) of objects found", array.count);
return nil;
}
return [array objectAtIndex:0];
Edit: This is in response to you asking about more details.
The code above can be its own function. I will give you a simple example of how you can use it.
-- In the VC where you have the table and are displaying the data
1: Let us assume your entity is called MyEntity and that it has an integer unique identifier field called myEntityUniqueId.
2: In your cellForRowAtIndexPath, you would write:
cell.tag = myCurrentEntity.myEntityUniqueId
-- Now lets go to your other VC where you want to retrieve the instance of MyEntity represented by the cell that was tapped.
1: Write the function:
-(void) findMyEntityForId:(int) tappedUniqueId
{
AppDelegate* appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext* context = [appDelegate managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"MyEntity" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"myEntityUniqueId ==%d", tappedUniqueId];
[fetchRequest setPredicate:predicate];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];
NSError* error;
NSArray* array = [context executeFetchRequest:request error:&error];
if (error)
{
NSLog(#"Error fetching data. %#", error);
return;
}
if (array.count != 1)
{
NSLog(#"Invalid number (%d) of objects found", array.count);
return;
}
MyEntity* foundResult = [array objectAtIndex:0]; // <-- This is the instance you are looking for.
}
2: Now call the above function with the correct argument.
I haven't tested the code but it should be fine.

How to edit the value of some attribute in entity?

How do I edit the value of some field in CoreData entity (SQLite) by tapping to Button?
For example, in my UITableViewCell I have button. I would like this button to change the value of some boolean field. By tapping first time I would like to write YES and second time - NO.
1.Join is a manually created join table Ingredients<->>Join<<->Recipes
2._ingredientInfo contain only 1 record
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"cellIngredient";
IngredientCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[IngredientCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
Ingredients *ingredient = [ingredientsArray_ objectAtIndex:indexPath.row];
cell.nameLabel.text = ingredient.name;
//Указываем что-то типа DataSource
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = appDelegate.managedObjectContext;
if (context != nil) {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"inRecipe == %# AND ingredient == %#", self.recipe, ingredient];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Join" inManagedObjectContext:context];
[request setEntity:entity];
[request setPredicate:predicate];
NSError *error = nil;
NSMutableArray *mutableFetchResult = [[context executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResult == nil) {
NSLog(#"No fetched objects!!!");
abort();
}
_ingredientInfo = [mutableFetchResult objectAtIndex:0];
}
cell.countLabel.text = [NSString stringWithFormat:#"%#", _ingredientInfo.count];
if (_ingredientInfo.inCart == [NSNumber numberWithInt:0]) {
cell.toCartBtn.imageView.image = [UIImage imageNamed:#"runTo.png"];
}
else {
cell.toCartBtn.imageView.image = [UIImage imageNamed:#"inCart.png"];
}
cell.unitLabel.text = ingredient.units;
return cell;
}
and when I tap the button cell.toCartBtn
- (IBAction)toCart:(id)sender
{
if (_ingredientInfo.inCart == [NSNumber numberWithInt:0]) {
_ingredientInfo.inCart = [NSNumber numberWithInt:1];
}
else {
_ingredientInfo.inCart = [NSNumber numberWithInt:0];
}
NSError *error = nil;
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if ([appDelegate.managedObjectContext save:&error]) {
[self.ingredientsTableView reloadData];
}
else {
NSLog(#"Error updating");
}
}
First fetch your object to be modified
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"entityName" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"(id == %#)", eID]];
NSError *error;
NSArray *details = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
entityName *objEntity= nil;
//error handling goes here
if([details count] > 0)
objEntity = (entityName *)[details objectAtIndex:0];
Now update that entity as you insert it
if(objEntity){
club.fieldName = #"YES";
NSError *error = nil;
if(![self.managedObjectContext save:&error])
NSLog(#"Error updating");
}

Resources