insert New Object & TreeViewt - iphone

App using tableview and NSFetchedResultsController.
NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
NSMutableArray *array=[[NSMutableArray alloc] init];
for (int i=0; i<[self.selectedEvents count]; i++) {
CustomDictionary *dic=[selectedEvents objectAtIndex:i];
if (dic.isSelected) {
Event *evt=[fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[array addObject:evt];
}
}
for (Event *evt in array) {
[context deleteObject:evt];
}
NSError *error;
if (![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
I got an error
Serious application error.
Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no object at index 1 in section at index 0'
In the code above selectedevents is an array whose count is equal to that of objects in fetched results controller.

Related

iOS 11 crash when save to coredata using NSManagedObjectContext

An ios11 application is crashing while saving to core data with a below exception, it is working fine in iOS10 and below.
Assertion failed: (moreParameters->mostRecentEntry == CFArrayGetValueAtIndex(stack, stackCount - 1)), function NSKeyValuePopPendingNotificationPerThread, file /BuildRoot/Library/Caches/com.apple.xbs/Sources/Foundation_Sim/Foundation-1444.12/EO.subproj/NSKeyValueObserving.m, line 933.
[context performBlockAndWait:^{
NSError *saveErr = nil;
if (![context save:&saveErr]) {
NSLog(#"Can't Save! %# %#", saveErr, [saveErr localizedDescription]);
}
}];
crash happening at if (![context save:&saveErr])
Below is NSManagedObject:
<ContentLanguage: 0x60000009f8b0> (entity: ContentLanguage; id: 0xd0000000000c0006 x-coredata://B53C7782-1231-4DB9-8579-77BFC31ADDA9/ContentLanguage/p3 ; data: {
displayName = "T\U00fcrk\U00e7e";
langId = tr;
relationship = "<relationship fault: 0x60400023c9e0 'relationship'>";
settings = nil;
user = "0xd000000000040002 x-coredata://B53C7782-1231-4DB9-8579-77BFC31ADDA9/User/p1";
})
ContentLanguage Entity

Using a file (CSV) instead of using CoreData

An app I'm building contains a catalogue of thousands of items, which need to be stored on the phone. Currently I am achieving this through CoreData, as logically it seemed like the best place to put it. I'm using GCD to run the CoreData insertion processes in the background and showing a progress bar / current percentage complete. This works as expected, however for only 5000 items, it's taking 8 minutes to complete on an iPhone 4. This application will be used on the 3GS and up, and will more likely contain 30/40 thousand items once it launches. Therefore this processing time is going to be horrifically long.
Is there any way I can use a CSV file or something to search through instead of storing each item in CoreData? I'm assuming there are some efficiency downfalls with an approach like this, but it would alleviate the excessive wait times. Unless there is another solution that would help with this problem.
Thanks.
EDIT:
I'm not sure how I'd go about saving the context at the end of the entire operation, as it uses a separate context within the loop. Any suggestions for this would be very much appreciated. I've got no idea how to progress with this.
Insertion Code Being Used
- (void) processUpdatesGCD {
NSArray *jsonArray=[NSJSONSerialization JSONObjectWithData:_responseData options:0 error:nil];
NSArray *products = [jsonArray valueForKey:#"products"];
NSArray *deletions;
if ([jsonArray valueForKey:#"deletions"] == (id)[NSNull null]){
self.totalCount = [products count];
} else {
deletions = [jsonArray valueForKey:#"deletions"];
self.totalCount = [products count] + [deletions count];
}
self.productDBCount = 0;
_delegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = _delegate.managedObjectContext;
self.persistentStoreCoordinator = [managedObjectContext persistentStoreCoordinator];
_managedObjectContext = managedObjectContext;
// Create a new background queue for GCD
dispatch_queue_t backgroundDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
for (id p in products) {
// id product = p;
// Dispatch the following code on our background queue
dispatch_async(backgroundDispatchQueue,
^{
id product = p;
// Because at this point we are running in another thread we need to create a
// new NSManagedContext using the app's persistance store coordinator
NSManagedObjectContext *backgroundThreadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[backgroundThreadContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
NSFetchRequest *BGRequest = [[NSFetchRequest alloc] init];
NSLog(#"Running.. (%#)", product);
[BGRequest setEntity:[NSEntityDescription entityForName:#"Products" inManagedObjectContext:backgroundThreadContext]];
[BGRequest setIncludesSubentities:NO];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"codes == %#", [product valueForKey:#"product_codes"]];
[BGRequest setPredicate:predicate];
NSError *err;
NSArray *results = [backgroundThreadContext executeFetchRequest:BGRequest error:&err];
if (results.count == 0){
// Product doesn't exist with code, make a new product
NSLog(#"Product not found for add/update (%#)", [product valueForKey:#"product_name"]);
NSManagedObject* newProduct;
newProduct = [NSEntityDescription insertNewObjectForEntityForName:#"Products" inManagedObjectContext:backgroundThreadContext];
[newProduct setValue:[product valueForKey:#"product_name"] forKey:#"name"];
[newProduct setValue:[product valueForKey:#"product_codes"] forKey:#"codes"];
if ([product valueForKey:#"information"] == (id)[NSNull null]){
// No information, NULL
[newProduct setValue:#"" forKey:#"information"];
} else {
NSString *information = [product valueForKey:#"information"];
[newProduct setValue:information forKey:#"information"];
}
} else {
NSLog(#"Product found for add/update (%#)", [product valueForKey:#"product_name"]);
// Product exists, update existing product
for (NSManagedObject *r in results) {
[r setValue:[product valueForKey:#"product_name"] forKey:#"name"];
if ([product valueForKey:#"information"] == (id)[NSNull null]){
// No information, NULL
[r setValue:#"" forKey:#"information"];
} else {
NSString *information = [product valueForKey:#"information"];
[r setValue:information forKey:#"information"];
}
}
}
// Is very important that you save the context before moving to the Main Thread,
// because we need that the new object is writted on the database before continuing
NSError *error;
if(![backgroundThreadContext save:&error])
{
NSLog(#"There was a problem saving the context (add/update). With error: %#, and user info: %#",
[error localizedDescription],
[error userInfo]);
}
// Now let's move to the main thread
dispatch_async(dispatch_get_main_queue(), ^
{
// If you have a main thread context you can use it, this time i will create a
// new one
// NSManagedObjectContext *mainThreadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
// [mainThreadContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
self.productDBCount = self.productDBCount + 1;
float progress = ((float)self.productDBCount / (float)self.totalCount);
int percent = progress * 100.0f;
// NSNumber *progress = [NSNumber numberWithFloat:((float)self.productDBCount / (float)self.totalCount)];
self.downloadUpdateProgress.progress = progress;
self.percentageComplete.text = [NSString stringWithFormat:#"%i", percent];
NSLog(#"Added / updated product %f // ProductDBCount: %i // Percentage progress: %i // Total Count: %i", progress, self.productDBCount, percent, self.totalCount);
if (self.productDBCount == self.totalCount){
[self updatesCompleted:[jsonArray valueForKey:#"last_updated"]];
}
});
});
}
if ([deletions count] > 0){
for (id d in deletions){
dispatch_async(backgroundDispatchQueue,
^{
id deleted = d;
// Because at this point we are running in another thread we need to create a
// new NSManagedContext using the app's persistance store coordinator
NSManagedObjectContext *backgroundThreadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[backgroundThreadContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
NSFetchRequest *BGRequest = [[NSFetchRequest alloc] init];
// NSLog(#"Running.. (%#)", deleted);
[BGRequest setEntity:[NSEntityDescription entityForName:#"Products" inManagedObjectContext:backgroundThreadContext]];
[BGRequest setIncludesSubentities:NO];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"codes == %#", [deleted valueForKey:#"product_codes"]];
[BGRequest setPredicate:predicate];
NSError *err;
NSArray *results = [backgroundThreadContext executeFetchRequest:BGRequest error:&err];
if (results.count == 0){
// Product doesn't exist with code, make a new product
NSLog(#"Product not found, can't delete.. %#", [deleted valueForKey:#"product_name"]);
} else {
NSLog(#"Product found, deleting: %#", [deleted valueForKey:#"product_name"]);
// Product exists, update existing product
for (NSManagedObject *r in results) {
[backgroundThreadContext deleteObject:r];
}
}
// Is very important that you save the context before moving to the Main Thread,
// because we need that the new object is writted on the database before continuing
NSError *error;
if(![backgroundThreadContext save:&error])
{
NSLog(#"There was a problem saving the context (delete). With error: %#, and user info: %#",
[error localizedDescription],
[error userInfo]);
}
// Now let's move to the main thread
dispatch_async(dispatch_get_main_queue(), ^
{
self.productDBCount = self.productDBCount + 1;
float progress = ((float)self.productDBCount / (float)self.totalCount);
int percent = progress * 100.0f;
// NSNumber *progress = [NSNumber numberWithFloat:((float)self.productDBCount / (float)self.totalCount)];
self.downloadUpdateProgress.progress = progress;
self.percentageComplete.text = [NSString stringWithFormat:#"%i", percent];
NSLog(#"Deleted product %f // ProductDBCount: %i // Percentage progress: %i // Total Count: %i", progress, self.productDBCount, percent, self.totalCount);
if (self.productDBCount == self.totalCount){
[self updatesCompleted:[jsonArray valueForKey:#"last_updated"]];
}
/*
*
* Change the completion changes to a method. Check to see if the total number of products == total count. If it does, run the completion method.
*
*/
});
});
}
}
}
Put the IF inside the dispatch, run one save at the end
// Create a new background queue for GCD
dispatch_queue_t backgroundDispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
// id product = p;
// Dispatch the following code on our background queue
dispatch_async(backgroundDispatchQueue,
^{
NSManagedObjectContext *backgroundThreadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[backgroundThreadContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
for (id p in products) {
id product = p;
// Because at this point we are running in another thread we need to create a
// new NSManagedContext using the app's persistance store coordinator
NSFetchRequest *BGRequest = [[NSFetchRequest alloc] init];
NSLog(#"Running.. (%#)", product);
[BGRequest setEntity:[NSEntityDescription entityForName:#"Products" inManagedObjectContext:backgroundThreadContext]];
[BGRequest setIncludesSubentities:NO];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"codes == %#", [product valueForKey:#"product_codes"]];
[BGRequest setPredicate:predicate];
NSError *err;
NSArray *results = [backgroundThreadContext executeFetchRequest:BGRequest error:&err];
if (results.count == 0){
// Product doesn't exist with code, make a new product
NSLog(#"Product not found for add/update (%#)", [product valueForKey:#"product_name"]);
NSManagedObject* newProduct;
newProduct = [NSEntityDescription insertNewObjectForEntityForName:#"Products" inManagedObjectContext:backgroundThreadContext];
[newProduct setValue:[product valueForKey:#"product_name"] forKey:#"name"];
[newProduct setValue:[product valueForKey:#"product_codes"] forKey:#"codes"];
if ([product valueForKey:#"information"] == (id)[NSNull null]){
// No information, NULL
[newProduct setValue:#"" forKey:#"information"];
} else {
NSString *information = [product valueForKey:#"information"];
[newProduct setValue:information forKey:#"information"];
}
} else {
NSLog(#"Product found for add/update (%#)", [product valueForKey:#"product_name"]);
// Product exists, update existing product
for (NSManagedObject *r in results) {
[r setValue:[product valueForKey:#"product_name"] forKey:#"name"];
if ([product valueForKey:#"information"] == (id)[NSNull null]){
// No information, NULL
[r setValue:#"" forKey:#"information"];
} else {
NSString *information = [product valueForKey:#"information"];
[r setValue:information forKey:#"information"];
}
}
}
// Is very important that you save the context before moving to the Main Thread,
// because we need that the new object is writted on the database before continuing
// Now let's move to the main thread
dispatch_async(dispatch_get_main_queue(), ^
{
// If you have a main thread context you can use it, this time i will create a
// new one
// NSManagedObjectContext *mainThreadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
// [mainThreadContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
self.productDBCount = self.productDBCount + 1;
float progress = ((float)self.productDBCount / (float)self.totalCount);
int percent = progress * 100.0f;
// NSNumber *progress = [NSNumber numberWithFloat:((float)self.productDBCount / (float)self.totalCount)];
self.downloadUpdateProgress.progress = progress;
self.percentageComplete.text = [NSString stringWithFormat:#"%i", percent];
NSLog(#"Added / updated product %f // ProductDBCount: %i // Percentage progress: %i // Total Count: %i", progress, self.productDBCount, percent, self.totalCount);
NSDate *currentProcessedDate = [NSDate date];
NSTimeInterval timeSinceStarted = [currentProcessedDate timeIntervalSinceDate:self.startProcessing];
NSInteger remainingProcesses = self.totalCount - self.productDBCount;
float timePerProcess = timeSinceStarted / (float)self.productDBCount;
float remainingTime = timePerProcess * (float)remainingProcesses;
self.timeRemaining.text = [NSString stringWithFormat:#"ETA: %0.0f minutes", fmodf(remainingTime, 60.0f)];
if (self.productDBCount == self.totalCount){
[self updatesCompleted:[jsonArray valueForKey:#"last_updated"]];
}
/*
*
* Change the completion changes to a method. Check to see if the total number of products == total count. If it does, run the completion method.
*
*/
});
}
NSError *error;
if(![backgroundThreadContext save:&error])
{
NSLog(#"There was a problem saving the context (add/update). With error: %#, and user info: %#",
[error localizedDescription],
[error userInfo]);
}
});
Ok, here's your problem.
Every time you insert a record, you do a save operation to the context.
Now, don't do it, that's what takes alot of time.
Do the save operation once, in the end of the loop, not every time you insert a record.
In your case I would check what is really time consuming?
Is it downloading data, is it importing data to CoreData?
Where do you get data from? Do you download it or you have it in Application Bundle?
CoreData is faster then CSV file. So it wont make your app faster.
Some tricks:
While importing data just save context at the end of the process. Do not save context in a loop.
If you do not need to download data and can put in the bundle, you can create coredata file in the simulator, put in the bundle and copy the file on first launch. It is really much more faster then importing data.

iOS+ Parse.com : kPFCachePolicyCacheThenNetwork, retrieve data two times

I have build an iOS app using Parse.com
I want to retrieve data from cache initially & then from network
For this i have used kPFCachePolicyCacheThenNetwork cache policy wchich is opt for my requirement.
PFQuery *employesquery = [PFQuery queryWithClassName:#"employesTable"];
[employesquery whereKey:#"UserID" equalTo:[PFUser currentUser]];
[employesquery includeKey:#"empID"];
[employesquery includeKey:#"empID.user"];
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
//APPLIES CACHE... ********
employesquery.cachePolicy = kPFCachePolicyCacheThenNetwork;
[employesquery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
[hud hide:YES];
NSMutableArray *empData = [[NSMutableArray alloc] init];
for (PFObject *object in objects)
{
//Getting Data For Item
PFObject *employeeObject = [object objectForKey:#"empID"];
[empData addObject:employeeObject];
}
[self fetchEmployeeData:empData];
}];
But using this Each data retrieve two times, repeatable data.
How to avoid this repeatable data,
Once the data is getting from networks the previously shown data (using cache) gets cleared/ hidden.
I have tried with [PFQuery clearAllCachedResults];
It was cleared all the cache so that there no data in cache for the next iteration.
When using kPFCachePolicyCacheThenNetwork as your caching policy your callback is always triggered twice. This is because the policy is to use the cache and then go to the network, not to use the cache exclusively.
The solution is to keep track of how many times your block has been called, so you can establish whether you're getting the cached result or the fresh result from the network. Parse have more information about this here.
You must clear the data array which is used for store objects queried from parse in the block findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error).
- (void)refreshData
{
PFUser *currentUser = [PFUser currentUser];
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"%# = '%#' OR %# = '%#'",
kMessageUserSendIdKey, currentUser.objectId,
kMessageUserReceiveIdKey, currentUser.objectId]];
PFQuery *query = [PFQuery queryWithClassName:kMessageClassKey predicate:predicate];
[query addDescendingOrder:kMessageTimeCreatedKey];
[query includeKey:kMessageUserSendKey];
[query includeKey:kMessageUserReceiveKey];
[query setCachePolicy:kPFCachePolicyCacheThenNetwork];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// TODO: Clear the data array
self.messagesDataArray = [NSMutableArray new];
if (objects.count > 0) {
[self.messagesDataArray addObject:objects[0]];
for (int i = 1; i < objects.count; i++) {
PFObject *messageChat = [objects objectAtIndex:i];
if (![self isExistWithMessageChat:messageChat]){
[self.messagesDataArray addObject:messageChat];
}
}
[self.tableView reloadData];
}
}
else {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}

ObjectAtIndex causes app to crash

When I do an NSLog of the contents of my NSMutableArray, it returns :
(
hat,
hat
)
So why is it that when I do an NSLog like so NSLog(#"%#", [pro.matches objectAtIndex:0]); it crashes with the error: *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
So strange
This is where I fill it:
[self.matches removeAllObjects];
NSArray *JSONarray = [[NSArray alloc] initWithArray:[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil]];
int i;
for (i=0; i<[JSONarray count]; i++) {
//[self.matches addObject:[JSONarray objectAtIndex:i]];
[self.matches addObject:#"hat"];
}
//NSLog(#"boys with bo%#", [[matches objectAtIndex:1] objectForKey:#"host"]);
block();
//JSON and add to matches.
}
}];
block();
and this is where i call it:
[pro refreshMatchesWithCallback:^
{
//[self.tableView reloadData];
NSLog(#"the count of a lifetime is %#", [pro.matches objectAtIndex:0]);
}];
When you first log the contents it has nothing in due to the way completion blocks work, try this:
[pro refreshMatchesWithCallback:^
{
//[self.tableView reloadData];
if(pro.matches.count > 0) {
NSLog(#"the count of a lifetime is %#", [pro.matches objectAtIndex:0]);
}
}];
Hope this Helps!
Sam
always prefer to use this approach
for(Object* obj in arra)
{
...
}
this will enter in loop if the counter is greater than 0. no check needed
Cheerz :P

Losing NSManaged Objects in my Application

I've been doing quite a bit of work on a fun little iPhone app. At one point, I get a bunch of player objects from my Persistant store, and then display them on the screen. I also have the options of adding new player objects (their just custom UIButtons) and removing selected players.
However, I believe I'm running into some memory management issues, in that somehow the app is not saving which "players" are being displayed.
Example: I have 4 players shown, I select them all and then delete them all. They all disappear. But if I exit and then reopen the application, they all are there again. As though they had never left. So somewhere in my code, they are not "really" getting removed.
MagicApp201AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
context = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *desc = [NSEntityDescription entityForName:#"Player" inManagedObjectContext:context];
[request setEntity:desc];
NSError *error;
NSMutableArray *objects = [[[context executeFetchRequest:request error:&error] mutableCopy] autorelease];
if (objects == nil) {
NSLog(#"Shit man, there was an error taking out the single player object when the view did load. ", error);
}
int j = 0;
while (j < [objects count]) {
if ([[[objects objectAtIndex:j] valueForKey:#"currentMultiPlayer"] boolValue] == NO) {
[objects removeObjectAtIndex:j];
j--;
}
else {
j++;
}
}
[self setPlayers:objects]; //This is a must, it NEEDS to work Objects are all the players playing
So in this snippit (in the viewdidLoad method), I grab the players out of the persistant store, and then remove the objects I don't want (those whose boolValue is NO), and the rest are kept. This works, I'm pretty sure. I think the issue is where I remove the players. Here is that code:
NSLog(#"Remove players");
/**
For each selected player:
Unselect them (remove them from SelectedPlayers)
Remove the button from the view
Remove the button object from the array
Remove the player from Players
*/
NSLog(#"Debugging Removal: %d", [selectedPlayers count]);
for (int i=0; i < [selectedPlayers count]; i++) {
NSManagedObject *rPlayer = [selectedPlayers objectAtIndex:i];
[rPlayer setValue:[NSNumber numberWithBool:NO] forKey:#"currentMultiPlayer"];
int index = [players indexOfObjectIdenticalTo:rPlayer]; //this is the index we need
for (int j = (index + 1); j < [players count]; j++) {
UIButton *tempButton = [playerButtons objectAtIndex:j];
tempButton.tag--;
}
NSError *error;
if ([context hasChanges] && ![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
UIButton *aButton = [playerButtons objectAtIndex:index];
[players removeObjectAtIndex:index];
[aButton removeFromSuperview];
[playerButtons removeObjectAtIndex:index];
}
[selectedPlayers removeAllObjects];
NSError *error;
if ([context hasChanges] && ![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
NSLog(#"About to refresh YES");
[self refreshAllPlayers:YES];
The big part in the second code snippet is I set them to NO for currentMultiPlayer. NO NO NO NO NO, they should NOT come back when the view does load, NEVER ever ever. Not until I say so. No other relevant part of the code sets that to YES. Which makes me think... perhaps they aren't being saved. Perhaps that doesn't save, perhaps those objects aren't being managed anymore, and so they don't get saved in. Is there a lifetime (metaphorically) of NSManaged object? The Players array is the same I set in the "viewDidLoad" method, and SelectedPlayers holds players that are selected, references to NSManagedObjects. Does it have something to do with Removing them from the array? I'm so confused, some insight would be greatly appreciated!!
It looks like you're removing your player objects from your various internal arrays, but not deleting them from the NSManagedObjectContext itself.
After a lot more debugging (Quite a bit) I found the issue. The code worked fine, until you "Removed" the first player, or the player in slot 0. I looked at when the players are filtered:
while (j < [objects count]) {
if ([[[objects objectAtIndex:j] valueForKey:#"currentMultiPlayer"] boolValue] == NO) {
[objects removeObjectAtIndex:j];
j--;
}
else {
j++;
}
}
And realized that if the first player is not playing, then j becomes -1, and then it breaks out of the loop and fails to validate the rest of the players, causing the weird bug to have them all back in the game. It had nothing to do with memory management at all, but I did fix some leaks in my effort to find the bug. Thank you!