Load CoreData objects' string property into UIPickerView - uitableview

Currently I have an entity named "Events" in a CoreData app. "Events" has one string property named "eventName".
In the -(void)viewDidLoad I am trying to Fetch all the "Events" objects and load their "eventName" by alphabetical order into a UIPickerView.
The ultimate end goal is through the use of a textField, buttons and the pickerView being add new objects in and remove unwanted objects out. Basically turning the UIPickerView into a UITableView. Currently I am able to save objects to the CoreData store, but am not able to pull them/their properties out into the UIPickerView.
I am willing and able to share the project source code to anyone who wants it, or is willing to look at it to help out.
thanks
Chris

-(void)update
{
NSMutableArray *array2 = [[NSMutableArray alloc] init];
CDPickerAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *moc = [appDelegate managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Event" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"callName" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
NSArray *array = [moc executeFetchRequest:request error:&error];
for (int i=0; i<array.count; i++) {
Event *theEvent = [array objectAtIndex:i];
NSString *StringOne = [NSString stringWithFormat:#"%#",theEvent.callName];
[array2 addObject:StringOne];
}
self.pickerData = array2;
[singlePicker reloadAllComponents];
}
-(IBAction)addCall{
CDPickerAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *theEvent = [NSEntityDescription insertNewObjectForEntityForName:#"Event" inManagedObjectContext:context];
[theEvent setValue:callField.text forKey:#"callName"];
[context save:&error];
callField.text=#"";
[callField resignFirstResponder];
self.update;
}

Related

Objective C: unrecognized selector sent to instance 0x6080000550c0

Here, m try to sort the array when refersh the tableview but is crash the application when refresh tableview.
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[_PFArray
sortUsingDescriptors:]: unrecognized selector sent to instance
0x6080000550c0'
#interface TableViewController () {
NSMutableArray *returnArray;
}
#end
- (void)viewDidAppear:(BOOL)animated {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate manageObjectContext];
NSError *error = nil;
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Resgistration" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
[request setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObjects:#"Unique",nil]];
returnArray = [[NSMutableArray alloc] init];
returnArray = [context executeFetchRequest:request error:&error];
for(Resgistration* reg in returnArray) {
NSLog(#"%#", reg);
NSLog(#"%#", reg.roshan);
}
[self.tableView reloadData];
UIColor *gray = [UIColor colorWithRed:234/255.0 green:234/255.0 blue:234/255.0 alpha:1.0];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:#"Please Wait"];
[refreshControl setBackgroundColor:gray];
[refreshControl addTarget:self action:#selector(sortArray) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
}
- (void)sortArray
{
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES selector:#selector(localizedStandardCompare:)];
NSMutableArray *sortDescriptior = [[NSMutableArray alloc] initWithObjects:sort, nil];
[returnArray sortUsingDescriptors:sortDescriptior]; // crash the app
[self.tableView reloadData];
[self.refreshControl endRefreshing];
}
Please help me to fix this problem. Thank you.
_PFArray is a subclass of NSArray and is immutable. You can use sortUsingDescriptors: on mutable array only, hence the crash.
It looks like somewhere along the code you have assigned instance of CoreData array inside returnArray variable. There you must use mutableCopy method to convert the immutable array to its mutable version, something like this:
returnArray = [<data array fetched from core data> mutableCopy];
Edit after looking at complete code
returnArray = [[context executeFetchRequest:request error:&error] mutableCopy];

Tableview cell is reloaded multiple table cell each time when its loaded

Im making a fetch request as follows,
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:#"PendingShipmentDetails"];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"PendingShipmentDetails" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
then im adding the fetched records to an array as follows within viewDidLoad method...
NSArray *result = [self.managedObjectContext executeFetchRequest:request error:&error];
if (result.count > 0) {
int i;
amountArray = [[NSMutableArray alloc] init];
statusArray = [[NSMutableArray alloc]init];
shipmentReferenceNumberArray = [[NSMutableArray alloc]init];
invoiceNumberArray = [[NSMutableArray alloc]init];
for (i = 0; i < [result count]; i++) {
pending = (NSManagedObject *)[result objectAtIndex:i];
[shipmentReferenceNumberArray addObject:[pending valueForKey:#"shipmentno"]];
[invoiceNumberArray addObject:[pending valueForKey:#"invoice_no"]];
[amountArray addObject:[pending valueForKey:#"amount"]];
[statusArray addObject: [pending valueForKey:#"status"]];
}
} else {
NSLog(#"SORRY");
}
The problem is that, since adding the objects within for loop, the table cell is being populated with same value multiple times each time when Im navigating towards it. However if im adding the elements to array, outside the for loop, only one element is being added and hence only one table cell is visible at anytime. How can I get this issue sorted?
You are going in quite wrong direction
Instead of using for loop you can use enumerateObjectsUsingBlock
[ChildList enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL * _Nonnull stop) {
Child = (ChildListModel*)[[ObjectBuilder builder] objectFromJSON:obj className:NSStringFromClass([ChildListModel class])];
if (Child) {
[originalList addObject:Child];
}
}];
Once all the elements are added in array then reload tableView,So it will return the row count as count of the array and will populated data once for each.
+ (NSArray *)fetchCoreData
{
AppDelegate * app = [[UIApplication sharedApplication]delegate];
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription * entity = [NSEntityDescription entityForName:#"PendingShipmentDetails" inManagedObjectContext:app.managedObjectContext];
[fetchRequest setEntity:entity];
NSError * error;
NSArray * fetchedObjects = [app.managedObjectContext executeFetchRequest:fetchRequest error:&error];
NSLog(#"Saved Data %#", fetchedObjects);
if (fetchedObjects != nil) {
return fetchedObjects;
}else{
return nil;
}
}
Try this ... i have this method fetchCoreData in my modal class. And this works perfectly for me.
Add the fetched data to array.

Fetching data from core data using GCD causes issue IOS

Hi I am developing IOS application in which I am using core data. In my application I am using split view controller. So my split view controller's master view contains following things:
-(void) viewWillAppear:(BOOL)animated
{
[self getNotificationCounter];
[self getTicketCounter];
}
-(void) getNotificationCounter:(UITableViewCell *) cell
{
dispatch_queue_t myQueue = dispatch_queue_create("My Notification Queue",NULL);
dispatch_async(myQueue, ^{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"NotificationsData" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; dispatch_async(dispatch_get_main_queue(), ^{
//update view;
});
});
}
-(void) getTicketCounter:(UITableViewCell *) cell
{
dispatch_queue_t myQueue = dispatch_queue_create("My Ticket Queue",NULL);
dispatch_async(myQueue, ^{
NSFetchRequest *ticketFetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *ticketEntity = [NSEntityDescription
entityForName:#"Tickets" inManagedObjectContext:context];
[ticketFetchRequest setEntity:ticketEntity];
NSError *ticketError = nil;
NSArray *ticketFetchedObjects = [context executeFetchRequest:ticketFetchRequest error:&ticketError];
dispatch_async(dispatch_get_main_queue(), ^{
// update view
});
});
}
and detail view controller have following thing.
- (NSFetchedResultsController *)fetchedResultsController {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#“channels” inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:#"channelId" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
So my problem is like this :
In my detail view controller I have one NSFetchRequestController and in master view have two
two NSFetchRequest with two GCD. if I start my application in portrait mode its works fine. But in landscape mode it stops without giving any error. Another thing If remove one GCD NSFetchRequest from master controller it works fine Or if I remove NSFetechResultController then also it works fine. Why it is so? Am I doing some thing wrong. Need Some help. Thank you.
You may not let NSManagedObjectContext or NSManagedObject cross threads.
You must create a fresh context for your thread.
dispatch_queue_t myQueue = dispatch_queue_create("My Ticket Queue",NULL);
dispatch_async(myQueue, ^{
NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] init];
threadContext.parent = context; //assumes other context is NSMainThreadConcurrencyType
NSFetchRequest *ticketFetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *ticketEntity = [NSEntityDescription
entityForName:#"Tickets" inManagedObjectContext:threadContext];
[ticketFetchRequest setEntity:ticketEntity];
...
To get NSManagedObject between contexts use it's objectID property and [NSManagedObjectContext objectWithId:]
Should you make edits then you will need to save the thread context. Those changes will propagate automatically down to the parent context.
Otherwise you discard the context at the end of the block like a sheet of paper.
EDIT
Also if the count of the objects is the only thing you want then you can use
countForFetchRequest:error: on NSManagedObjectContext
This will be a cheaper call because no objects are created for you.

Core data objects update through loop

I have a tableView showing core-data objects. On the same view there are five buttons. Each button action should update the value of an attribute from the objects.
As an example, I will show you what I have to update the attribute 'isDone':
- (IBAction)allDoneAction:(id)sender {
NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
int i=0;
for (NSManagedObject *mo in context)
{
[mo setValue:#"Done" forKey:#"isDone"];i++;
}
[managedObjectContext save:nil];
}
This method throws following following exception:
NSManagedObjectContext countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x9a6b0a0
2014-01-06 19:01:43.862 To-Do Pro[679:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObjectContext countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x9a6b0a0'
What do I need to avoid the exception and obtain the desired update?
Here is my NSFetchedResultsController:
- (NSFetchedResultsController *)fetchedResultsController
{
if (fetchedResultsController) return fetchedResultsController;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity =
[NSEntityDescription entityForName:#"FavoriteThing"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"displayOrder"
ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]
initWithObjects:sortDescriptor, nil];
//SOLO TO-DOS DE TODAY
todayDate = [NSDate date];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:todayDate]; // Get necessary date components
NSNumber *yearBuscado = [NSNumber numberWithLong:[components year]];
NSNumber *mesBuscado = [NSNumber numberWithLong:[components month]];
NSNumber *diaBuscado = [NSNumber numberWithLong:[components day]];
// NSString *tipourgente = #"Urgent";
// NSString *tipocolor = #"Yellow";
NSString *textoNotDone = #"Not done";
NSString *textoNotDeleted = #"Not deleted";
NSPredicate *yearPredicate = [NSPredicate predicateWithFormat:#"todoYear == %#", yearBuscado];
NSPredicate *monthPredicate = [NSPredicate predicateWithFormat:#"todoMonth == %#", mesBuscado];
NSPredicate *dayPredicate = [NSPredicate predicateWithFormat:#"todoDay == %#", diaBuscado];
NSPredicate *notDonePredicate = [NSPredicate predicateWithFormat:#"isDone== %#", textoNotDone];
NSPredicate *notDeletedPredicate = [NSPredicate predicateWithFormat:#"isSemiDeleted==%#", textoNotDeleted];
// NSPredicate *urgentPredicate = [NSPredicate predicateWithFormat:#"urgent == %#", tipourgente];
// NSPredicate *colorPredicate = [NSPredicate predicateWithFormat:#"color == %#", tipocolor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSPredicate *busqueda = [NSCompoundPredicate andPredicateWithSubpredicates:#[yearPredicate,monthPredicate,dayPredicate,notDonePredicate,notDeletedPredicate]];
[fetchRequest setPredicate:busqueda];
NSFetchedResultsController *aFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
[self setFetchedResultsController:aFetchedResultsController];
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController;
}
Ok, I know absolutely nothing about core data, but from what I have researched in the last two minutes it appears as though you do not loop over An object of NSManagedObjectContext. You need to create a search within the context and get the results from that. Then iterate through the results and modify willy nilly.
Here is an example taken from this answer:
NSManagedObjectContext * context = [self managedObjectContext];
NSFetchRequest * fetch = [[[NSFetchRequest alloc] init] autorelease];
[fetch setEntity:[NSEntityDescription entityForName:#"ShoppingBasket" inManagedObjectContext:context]];
NSArray * result = [context executeFetchRequest:fetch error:nil];
for (id basket in result)
[context deleteObject:basket];
So get the context, Create a search, get an array from the context based on the search criteria, loop through the results and do as you will with updating them.
If you are using a fetchedResultsController already to populate the tableView then you can iterate over the objects in the fetchedResultsController like this:
- (IBAction)allDoneAction:(id)sender {
NSArray *objects = [fetchedResultsController fetchedObjects];
for (NSManagedObject *mo in objects) {
[mo setValue:#"Done" forKey:#"isDone"];i++;
}
NSError *error;
bool result = [[fetchedResultsController managedObjectContext] save:&error];
if (!result) {
NSLog(#" error saving context, %#, %#", error, error.userInfo);
}
}
BTW you should be checking for errors in your call to save so don't pass in nil.

fetching particular predicate from database

I have 4 CoreData database. Each actually having their own value. But it is too heavy and i would like to reduce it to 1 Database. So each time i want to pull information from the database, i can choose what to pull. I need to use NSPredicate to set the string that i want to pull izzit?
Do i set my NSPredicate like this?
NSString *value = #"Food";
NSString *wildcardedString = [NSString stringWithFormat:#"%#*", value];
[[NSPredicate predicateWithFormat:#"ANY places.type like %#", wildcardedString];
and how do i bind the NSPredicate with the fetch request sequence?
this is my fetchedResultsController
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil)
{
return fetchedResultsController;
}
CoreDataMelakaAppDelegate *appDelegate = (CoreDataMelakaAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
[fetchRequest setEntity:[NSEntityDescription entityForName:#"WhereTo" inManagedObjectContext:context]];
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES] autorelease];
NSArray *sortDescriptors = [[[NSArray alloc] initWithObjects:sortDescriptor, nil] autorelease];
[fetchRequest setSortDescriptors:sortDescriptors];
// NSPredicate *pred = [NSPredicate predicateWithFormat:#"(name = %#)", wher.name];
//[fetchRequest setPredicate:pred];
NSString *value = #"Nasi";
NSString *wildcardedString = [NSString stringWithFormat:#"%#*", value];
[[NSPredicate predicateWithFormat:#"ANY wher.name like %#", wildcardedString];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
return fetchedResultsController;
}
When you alter the predicate of a fetch request used by a fetched results controller (FRC), you have to create a new fetched results controller.
Your code is fine logically but it only creates a FRC once with a predicate that compiles to:
ANY wher.name like Nasi*
... each time the FRC executes its fetch, it use that exact predicate.
If you want to use a flexible predicate, you will need to create a new FRC every time you change the predicate.

Resources