i want to add a NSArray to my NSMutable ( init in the appdelegate )
this is my code, the method is call each time a button (male, female, couple) is pressed so an NSArray has to be add to the MutableArray but i don't know i tried stuff but doesnt work. :
- (void) sexChoosen:(NSString *) sexe
{
NSError *err;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Boxes" inManagedObjectContext:context];
[request setEntity:entity];
NSArray *arrayForPredicate = [context executeFetchRequest:request error:&err];
NSPredicate *sex;
sex = [NSPredicate predicateWithFormat:#"sexe = %#", sexe];
NSArray *BoxWithSex = [arrayForPredicate filteredArrayUsingPredicate:sex];
//NSMutableArray* tmp = [self createMutableArray:BoxWithSex];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSLog(#"FIRST %#", appDelegate.myArray);
// HERE IS THE CODE TO ADD THE ARRAY TO MY NSMUTABLE ARRAY = AppDelegate *appDelegate
NSLog(#"SECOND %#", appDelegate.myArray);
}
From the NSMutableArray documentation:
"addObjectsFromArray: Adds the objects contained in another given array
to the end of the receiving array’s content."
Related
I am having this strange issue which has been plaguing me all day, i am updating an object in a background thread which is saving correctly
NSFetchRequest *fetchRequest1 = [[NSFetchRequest alloc] init];
NSEntityDescription *entity1 = [NSEntityDescription entityForName:#"STMilestone"
inManagedObjectContext:tmpContext];
[fetchRequest1 setEntity:entity1];
[fetchRequest1 setReturnsObjectsAsFaults:NO];
NSError *error;
NSString *idNum = [obj valueForKey:#"id"];
// NSUInteger TrackerExists = [tmpContext countForFetchRequest:fetchRequest1 error:&error];
[fetchRequest1 setPredicate:[NSPredicate predicateWithFormat:#"identiferNumber = %#", idNum]];
NSArray *logs = [tmpContext executeFetchRequest:fetchRequest1 error:&error];
NSManagedObject *updateObj = [logs objectAtIndex:0];
[updateObj setValue:[NSNumber numberWithInt:20] forKey:#"progress"];
When i then get this object in the same background thread this gets the correct updated value
However when i go to get this updated value on my main thread it returns the old value, then when i clear the cache and reload the app it pulls the correct data
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"STTracker"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSError *error = nil;
NSMutableArray *array = [NSMutableArray arrayWithArray:[context executeFetchRequest:fetchRequest error:&error]];
I think this may be a context issue, my background thread context is being created with this
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *tmpContext = [[NSManagedObjectContext alloc] init];
tmpContext.persistentStoreCoordinator = [appDelegate persistenceCoordinator];
and the main thread is
NSPersistentStoreCoordinator *coordinator = [self persistenceCoordinator];
if(coordinator != nil)
{
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
NSUndoManager *undoManager = [[NSUndoManager alloc] init];
[undoManager setGroupsByEvent:NO];
[_managedObjectContext setUndoManager:undoManager];
}
[_managedObjectContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
However i have updated other objects in my app and they are being pulled through, so any help or insight on why this might be happening would be great
This will not work:
NSManagedObjectContext *tmpContext = [[NSManagedObjectContext alloc] init];
You need to need to init the context with the right concurrency type and assign it the correct parent context (or persistent store coordinator). See the docs
initWithConcurrencyType:
setParentContext:
When child and parent contexts are set up correctly, you an save the child context which does not really write to the persistent store but just "pushes" the changes up to the parent context. The changes are written to the store once you save the parent context again.
i have list of brands stored in Core Data, each brand is associated with multiple contents. The contents have a flag called downStatus which is used to denote whether a content is downloaded or not. The following method is used to fetch all the brands from Core data sorted with brand name
-(void)getDownloadedBrands{
AppDelegate *aAppDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSMutableArray *aBrands = [[NSMutableArray alloc] init];
NSEntityDescription *entity =
[NSEntityDescription entityForName:#"Brand" inManagedObjectContext:aAppDelegate.managedobjectcontext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
NSSortDescriptor *sort=[[NSSortDescriptor alloc]initWithKey:#"brandName" ascending:YES];
//NSSortDescriptor *sort1=[[NSSortDescriptor alloc]initWithKey:#"downStatus" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObjects:sort, nil]];
aBrands =(NSMutableArray *)[aAppDelegate.managedobjectcontext executeFetchRequest:request error:nil];
[request release];
[sort release];
NSLog(#"%#",aBrands);
brands = [[NSMutableArray alloc]initWithArray:aBrands];
aAppDelegate.dbBrandArr = brands;
[self loadGridView];
}
Now i want to sort using the downStatus which is in the Content. So it will be like, downloaded brands in Alphabetical Order and then Un-Downloaded brands in Alphabetical order. The downStatus takes two values 1 for downloaded 0 for not downloaded. Please help.
One way to do it is by making 2 fetchRequests to CoreData using the NSPredicate with value 1/0 on downStatus property and using the same alphabetical sortDescriptor.
Now create a new Array by adding the 0 array to the 1 array. In your code it would look something like this:
-(void)getDownloadedBrands{
AppDelegate *aAppDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
//2 arrays
NSMutableArray *aBrands0 = [[NSMutableArray alloc] init];
NSMutableArray *aBrands1 = [[NSMutableArray alloc] init];
//set entity en make requests
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Brand" inManagedObjectContext:aAppDelegate.managedobjectcontext];
NSFetchRequest *request0 = [[NSFetchRequest alloc] init];
NSFetchRequest *request1 = [[NSFetchRequest alloc] init];
[request0 setEntity:entity];
[request1 setEntity:entity];
//create sortDescriptor alphabetically
NSSortDescriptor *sort=[[NSSortDescriptor alloc]initWithKey:#"brandName" ascending:YES];
//create predicates on downStatus property
NSPredicate *predicate0 = [NSPredicate predicateWithFormat:#"downStatus == %#", [NSNumber numberWithBool:0]];
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"downStatus == %#", [NSNumber numberWithBool:1]];
//set predicates to the requests
[request0 setPredicate:predicate0];
[request1 setPredicate:predicate1];
//set sortDescriptor to both requests
[request0 setSortDescriptors:[NSArray arrayWithObjects:sort, nil]];
[request1 setSortDescriptors:[NSArray arrayWithObjects:sort, nil]];
//fetch arrays with downStatus 1/0
aBrands0 =(NSMutableArray *)[aAppDelegate.managedobjectcontext executeFetchRequest:request0 error:nil];
aBrands1 =(NSMutableArray *)[aAppDelegate.managedobjectcontext executeFetchRequest:request1 error:nil];
//release requests // NOT USING ARC??
[request0 release];
[request1 release];
[sort release];
//log results
NSLog(#"aBrands0: %#",aBrands0);
NSLog(#"aBrands1: %#",aBrands1);
//add object 0 array to 1 array
NSArray *combinedArray = [aBrands1 arrayByAddingObjectsFromArray:aBrands0];
//copy array to brands
brands = [[NSMutableArray alloc]initWithArray:combinedArray];
//set property on appDelegate
aAppDelegate.dbBrandArr = brands;
//reload tableView
[self loadGridView];
}
-- edit, adding answer for NSDictionary with downStatus key
-(void)getDownloadedBrands{
AppDelegate *aAppDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSMutableArray *aBrands = [[NSMutableArray alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Brand" inManagedObjectContext:aAppDelegate.managedobjectcontext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
NSSortDescriptor *sort=[[NSSortDescriptor alloc]initWithKey:#"brandName" ascending:YES];
//NSSortDescriptor *sort1=[[NSSortDescriptor alloc]initWithKey:#"downStatus" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObjects:sort, nil]];
aBrands =(NSMutableArray *)[aAppDelegate.managedobjectcontext executeFetchRequest:request error:nil];
NSMutableArray *aBrands0 = [[NSMutableArray alloc] init];
NSMutableArray *aBrands1 = [[NSMutableArray alloc] init];
for (NSDictionary *dict in aBrands) {
if ([dict valueForKeyPath:#"downStatus"] == YES)
{
//add to 1 array
[aBrands1 addObject:dict];
}
else
{
//add to 0 array
[aBrands0 addObject:dict];
}
}
//sort arrays
NSArray * array1 = [aBrands1 sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
NSArray * array0 = [aBrands0 sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
NSArray * allArray = [aBrands1 arrayByAddingObjectsFromArray:aBrands0];
//combine arrays
//copy array to brands
brands = [[NSMutableArray alloc]initWithArray:combinedArray];
//set property on appDelegate
aAppDelegate.dbBrandArr = brands;
//reload tableView
[self loadGridView];
[request release];
[sort release];
NSLog(#"%#",aBrands);
}
If you plan to use the fetch result in a UITableViewController, you could use the sectionNameKeyPath of your fetchedResultsController for the downStatus and keep your sort descriptor for the brand name. Can look like this:
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext
sectionNameKeyPath:#"customSectionTitle" cacheName:nil];
Place this in the header file of your NSManagedObject :
-(NSString*)customSectionTitle;
And this in .m :
-(NSString*)customSectionTitle{
if ([downStatus boolValue] == YES) {
return #"Downloaded";
}
else {return #"Not Downloaded";}
}
If you do not plan to use a fetchedResultsController, just sort first by downStatus and then by brand name.
I have been trying all afternoon to get the CoreData portion of my app working and almost have it working as it should. The problem is that the CoreData does not save appropriate value when the app gets terminated (removed from multitasking menu). The value that remains is the intitial value (in my case 0, defined as NSString) I put into the entity instead of the new value the user entered. So the issue is saving the new value PERMANENTLY after the app is closed and not showing the initial value again when the app is loaded
Entity name: Gameinfo
Attribute: score
I am not sure what I am doing wrong. If anyone could help me, it would be appreciated.
Thanks!
-(IBAction)saveTheory1
{
AppDelegate *appDelegate= [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context =
[appDelegate managedObjectContext];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Gameinfo"];
NSError *error = nil;
NSArray *someArray = [context executeFetchRequest:request error:&error];
[[someArray objectAtIndex:0] setValue:[self showKey] forKey:#"score"]; // showKey gets the text from UITextField
}
-(IBAction)showTheory1;
{
AppDelegate *appDelegate= [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context =
[appDelegate managedObjectContext];
NSEntityDescription *entityDesc =
[NSEntityDescription entityForName:#"Gameinfo"
inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSManagedObject *matches = nil;
NSError *error;
NSArray *objects = [context executeFetchRequest:request
error:&error];
matches = [objects objectAtIndex:0];
NSLog (#"show us the current value: %#", [matches valueForKey:#"score"]);
}
You are not saving the value at all. You are just assigning it to the Gameinfo object. To actually save it, call save: method on managed object context:
...
[[someArray objectAtIndex:0] setValue:[self showKey] forKey:#"score"];
NSError *saveError = nil;
[[appDelegate managedObjectContext] save:&saveError];
}
It doesnt look like you are calling [context save:error] anywhere. This is what moves your changes into permanent storage.
I have a helper class designed to get data from Core Data and pass it back to a view controller. Here's the code:
View Controller:
#interface AnnouncementsController : UIViewController
#property (nonatomic, retain) NSMutableArray *announcements;
#end
#implementation AnnouncementsController
#synthesize announcements;
- (void)viewDidLoad
{
AnnouncementCoreDataHelper *announcementHelper = [[AnnouncementCoreDataHelper alloc] init];
self.announcements = [announcementHelper selectAnnouncementsWithPredicate:#"isActive = 1" sortDescriptor:#"lastUpdated" sortAscending:NO];
[super viewDidLoad];
}
#end
And the Core Data Helper implementation:
// Select one or more announcements based on a predicate if passed in and a sort order
- (NSMutableArray*)selectAnnouncementsWithPredicate:(NSString *)predicateString sortDescriptor:(NSString *)sortBy sortAscending:(BOOL)isAscending
{
NSError *error = nil;
// Build the entity and request
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Announcement" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
if(predicateString)
{
// Set the search criteria
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
[request setPredicate:predicate];
}
if(sortBy)
{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortBy ascending:isAscending];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
}
// Perform the search
NSMutableArray *results = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if(results == Nil)
{
NSLog(#"%#", error);
}
return results;
}
The problem is that the Core Data Helper returns two objects in its NSMutableArray results but the View Controller's NSMutableArray announcements gets nil. What is getting lost in the passing the NSMutableArray back from the helper to the controller? If I change all the variables and results to a NSArray, everything works.
I believe this was a funky issue with Xcode. I clean and reran the build and everything is working. I apologize for wasting your time and thanks for the help! I would like to know more about the memory management issues though.
I have difficulties displaying objects coming from CoreData in a tableView.
I have 2 sorts of entities : Sample and SampleList. What is important to know is that a SampleList has an attribute sampleSet which is a set of samples (entity of Sample)
First I succeeded in displaying every SampleList. Here is viewDidLoad:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"SampleList" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"lastSampleDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
NSError *error;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// Handle error
}
[self setSampleListArray:mutableFetchResults];
[mutableFetchResults release];
[request release];
Once I click on a row in my tableView, I would like to display in another UITableView every sample from the SampleList selected.
I thought that I could pass to the subview SampleList mySampleList. But then, I don't know what to do with it as it is not organized.
How can I return an ordered array of Sample (ordered by dateSample attribute for example) ?
Thank you for your time !
You can just use NSSet and NSArray methods on sampleSet to get an ordered array:
sortedArray = [[sampleSet allObjects] sortedArrayUsingSelector:#selector(compare:)];
or if you want to specify particular sort descriptors instead of the regular "compare" method:
sortedArray = [[sampleSet allObjects] sortedArrayUsingDescriptors:sortDescriptors];