In my code, i'm creating 5 sets of objects, and 5 NSArrays containing those objects. At the end of my method, two of the arrays release properly, but the other three crash my application.
Creating
UIImageView *image0 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"TankAxe.png"]];
NSArray *imageArray = [[NSArray alloc] initWithObjects:image0, nil];
NSString *name0 = [NSString stringWithString:#"Pistol"];
NSArray *nameArray = [[NSArray alloc] initWithObjects:name0, nil];
NSNumber *price0 = [NSNumber numberWithInt:100];
NSArray *priceArray = [[NSArray alloc] initWithObjects:price0, nil];
NSNumber *round0 = [NSNumber numberWithInt:0];
NSArray *roundArray = [[NSArray alloc] initWithObjects:round0, nil];
NSNumber *priceRound0 = [NSNumber numberWithInt:0];
NSArray *priceRoundArray = [[NSArray alloc] initWithObjects:priceRound0, nil];
Releasing
[name0 release];
[nameArray release]; //Releases properly
[image0 release];
[imageArray release]; //Releases properly
[price0 release];
NSLog(#"%i",[priceArray retainCount]); //Returns 1
[priceArray release]; //Source of the crash
[round0 release];
[roundArray release]; //Also crashes
[priceRound0 release];
[priceRoundArray release]; //Also Crashes
Anybody know how to properly release the arrays containing NSNumbers?
price0, name0,round0, and priceRound0 should not be released. They were not created with alloc, and will be autoreleased by the methods that returned them.
Once you release an object that you shouldn't, the heap is corrupted, and the program could crash at any time.
The easiest way to debug this is to turn on zombies (Tip #1):
http://www.loufranco.com/blog/files/debugging-memory-iphone.html
Related
NSMutableDictionary *dic0 = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"string0", #"key0", nil];
NSDictionary *dic1 = [[NSDictionary alloc] initWithObjectsAndKeys:#"string1", #"key1", nil];
NSDictionary *dic2 = [[NSDictionary alloc] initWithObjectsAndKeys:#"string2", #"key2", nil];
NSDictionary *dic3 = [[NSDictionary alloc] initWithObjectsAndKeys:#"dic3", #"key3", nil];
NSArray *arrayOri = [[NSArray alloc] initWithObjects:dic0, dic1, dic2, nil];
//here means a deep copy
NSMutableArray *arrayDeepCopy = [[NSMutableArray alloc] initWithArray:arrayOri copyItems:YES];
NSRange range = {0, 2};
NSArray *subArray = [arrayOri subarrayWithRange:range];
[arrayDeepCopy addObject:dic3];
NSLog(#"arrayOri not merge %#", arrayOri);
//merge one object
[dic0 setObject:#"mutableV" forKey:#"mutableKey"];
//dealloc one object
[dic1 dealloc];
NSLog(#"arrayOri %# ", arrayOri);
NSLog(#"subArray %# ", subArray);
crash here,because of dic1 dealloced,if deep copy,why the original object has an effect with new object??
NSLog(#"array %# ", arrayDeepCopy);
what initWithArray:(NSArray *)array copyItems:(BOOL)flag do after all??
The problem is that dic1 is an immutable object. Thus is does not make sense to copy it in memory, and therefore arrayDeepCopy holds a pointer to the original dic1 object. When you deallocate it, it is gone from all arrays that store it.
If you want to have a true deep copy, you have to instantiate a NSMutableDictionary.
I have two entities, Job and Client. The relationship from job to client is called clientOfJob which is a many-to-one relationship:
Job<<-->Client
I am trying to understand how I would sort my fetch results into sections for the table view, with the sections based on client first names.
This is my first attempt to use sectionNameForKeyPath, but I am using sample code from CoreDataBooks, and so far, substituting some of that code has eliminated some serious problems I had earlier today.
Here is the code I tried. I didn't think it would work, but I'm not sure what I need to use for the client sort descriptor key and for the sectionNameKeyPath.
By the way, the code works well with only the jobSortDescriptor (without the clientSortDescriptor) and with sectionNameKeyPath set to nil. Then it just sorts by job description. I can get at the related client entity information, putting client name information into the detailedTextLabel of each cell while I have the job description in the textLabel of the cell.
- (NSFetchedResultsController *) fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription * entity = [NSEntityDescription entityForName:#"Job" inManagedObjectContext:dataInterface.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:10];
NSSortDescriptor *clientSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"clientOfJob.firstName" ascending:YES];
NSSortDescriptor *jobSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"jobDescription" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:clientSortDescriptor, jobSortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:dataInterface.managedObjectContext sectionNameKeyPath:#"clientOfJob.firstName" cacheName:#"Jobs"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[jobSortDescriptor release];
[clientSortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Unresolved Error %#, %#", error, [error userInfo]);
abort();
}
return fetchedResultsController;
}
I have an entity ("Settings") and I want to get all the values in just one field ("Status").I am using coredata. Can anyone help me, please?
Declare this in .h file:
NSMutableArray *eventArray;
and in .m file
- (void)fetchRecords {
// Setup the fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Define our table/entity to use
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Settings" inManagedObjectContext:managedObjectContext];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Status" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setEntity:entity];
[fetchRequest setEntity:entity];
NSError *error;
// Get array of results.
NSMutableArray *theResults = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
if (!theResults) {
// Handle the error.
// This is a serious error and should advise the user to restart the application
}
// Grab unique neighborhoods through NSSet.
NSSet *uniqueElements = [NSSet setWithArray:[theResults valueForKey:#"Status"]];
// Dump NSSet uniques into new array.
NSMutableArray *sortedResults = [[NSMutableArray alloc] initWithArray:[uniqueElements allObjects]];
for(int i = 0; i < [sortedResults count];i++)
{
NSLog(#"%d. %#", i+1, [sortedResults objectAtIndex:i]);
}
// Save our fetched data to an array
[self setEventArray: sortedResults];
}
At first, u can get Array of values:
NSFetchRequest *requestSettings = [[NSFetchRequest alloc] init];
[requestCodesList setEntity:[NSEntityDescription entityForName:#"Setting" inManagedObjectContext:managedObjectContext]];
NSArray *setting = [managedObjectContext executeFetchRequest:requestCodesList error:&error];
if (error) NSLog(#"Failed to executeFetchRequest to data store: %#", [error localizedDescription]);
Next, u transfer u array in NSString:
ComponentsJoinedByString: Constructs
and returns an NSString object that is
the result of interposing a given
separator between the elements of the
array.
(NSString *)componentsJoinedByString:(NSString *)separator
code is:
NSString *settingChanged = [setting componentsJoinedByString:#","];
And after u can using this anywhere in u UI (binding, setStringValue e.t.c)
Welcome
i use Core Data to store datas. i need such a method which returns only the last 7 elements of entity. my question is how should i modify this code ( it fetchs all of elements, but i need only last 7)
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Trip" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[ NSFetchRequest alloc] init];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"distance" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
NSError *error;
tripArray = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
Define last? Core Data does not have a concept of order internally. If you mean by the farthest away based on your distance property then you can do the following:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Trip" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[ NSFetchRequest alloc] init];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"distance" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[request setSortDescriptors:sortDescriptors];
[request setFetchLimit:7];
[sortDescriptor release];
NSError *error;
NSArray *tripArray = [managedObjectContext executeFetchRequest:request error:&error];
Note that the addition of the -setFetchLimit: will cause this request to only return 7 results. It will return the "first" 7 based on your sort. So if you want the closest, reverse the ascending: portion of your sort.
-mutableCopy
There is absolutely no point in calling -mutableCopy on the NSArray that is returned from -executeFetchRequest: error:. Adding objects to that NSArray will not add them to Core Data and removing them from that NSArray will not remove them from Core Data. Therefore it has absolutely no value and is just wasteful.
Do you remember where you saw that? I have been trying to track it down for a while now.
I am getting a memory leak when I add a sort descriptor to my Fetch Request in Core Data. If I comment out the NSSortDescriptor block it runs without a memory leak in Instruments.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Pools" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"game.league.id=%i",[lid intValue]];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"game.date" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
NSError *error;
NSArray *items = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
// Do Something
[fetchRequest release];
[items release];
Any ideas?
In the sort descriptor, you're walking a relationship using the keypath game.date.
Your leak is probably associated with one of those objects in the keypath. It disappears when you remove the sort because then the objects in the key path don't do anything.
If you have transient properties, custom accessors, non-entity properties etc in the game entity I would look there. Custom value transformers are also a good bet.
The stack in Instrument should tell you exactly which object is leaking.