iphone coredata setValue not working inside if statement - iphone

I have my coredata working fine, but when I put a setValue inside an if, it doesn't work,
this is the code>
-(void) salvalo {
StaffManagerAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *newDay;
newDay = [NSEntityDescription insertNewObjectForEntityForName:#"DaysAttendance"
inManagedObjectContext:context];
[newDay setValue:startday forKey:#"start"];
[newDay setValue:today forKey:#"datef"];
[newDay setValue:myNumber forKey:#"empID"];
[newDay setValue:myNumber2 forKey:#"intID"];
//[newDay setValue:internet forKey:#"sinch"];
NSError *error;
[context save:&error];
if ([internet isEqualToString:#"YES"] ) {
[self insertJson];
[newDay setValue:internet forKey:#"sinch"];
}
else {
[newDay setValue:#"NO" forKey:#"sinch"];
}
//[self.view removeFromSuperview];
[self dismissModalViewControllerAnimated:YES];
}
please note that when I use the code inside the if in the commented part
//[newDay setValue:internet forKey:#"sinch"];
, it saves normally that value (YES/NO) to the coredata, but inside the if, it doesnt work, even if I put al the delegate and context stuff inside the if,,
so what is the problem? how to fix it?
thanks a lot!

The line [context save:&error]; is before the if statements.
You may be setting the new value properly, just not saving. The problem might just be this oversight.

Related

Bad Access on Core Data deleteObject

I could use some assistance in debugging a EXC_BAD_ACCESS error received on the [context deleteObject:loan]; command. The error is received in the following delegate method:
- (void)didCancelNewLoan:(Loan *)loan {
// save the context
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
[context deleteObject:loan]; // *** EXC_BAD_ACCESS here ***
// This method is called from a the following method in a second class:
- (IBAction)cancel:(id)sender {
[delegate didCancelNewLoan:self.loan];
}
// The loan ivar is created by the original class
// in the below prepare for Segue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"NewLoan"]) {
UINavigationController *navController = (UINavigationController *)[segue destinationViewController];
LoanViewController *loanView = (LoanViewController *)[[navController viewControllers] lastObject];
loanView.managedObjectContext = self.managedObjectContext;
loanView.delegate = self;
loanView.loan = [self createNewLoan];
loanView.newLoan = YES;
}
// Finally, the loan is created in the above
// method's [self createNewLoan] command:
- (NSManagedObject *)createNewLoan {
//create a new instance of the entity managed by the fetched results controller
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
[newManagedObject setValue:[NSDate date] forKey:#"timeStamp"];
CFUUIDRef uuid = CFUUIDCreate(NULL);
CFStringRef uuidstring = CFUUIDCreateString(NULL, uuid);
//NSString *identifierValue = (__bridge_transfer NSString *)uuidstring;
[newManagedObject setValue:(__bridge_transfer NSString *)uuidstring forKey:#"identifier"];
CFRelease(uuid);
CFRelease(uuidstring);
NSError *error;
[self.fetchedResultsController performFetch:&error];
NSLog(#"%i items in database", [[self.fetchedResultsController fetchedObjects] count]);
return newManagedObject;
}
Appreciate your looking at the above methods.
Guess #1: you are accessing a deallocated object. To debug: turn on zombies and see what happens.
Update: here's how you turn on zombies in Xcode 5:
Product > Scheme > Edit Scheme, select Diagnostics tab, check "Enable Zombie Objects"
for older Xcode
, edit your build settings, add and enable these arguments in your build scheme:
Guess #2: you have a multithreaded app and you are accessing a managed object context from different threads, which is a no no.
You can add an assert before your delete:
assert( [ NSThread isMainThread ] ) ;
From looking at your code above, there's nothing that stands out as being done incorrectly.
I am wondering whether you are dealing with two different managed object contexts without realising it? You will have to set some breakpoints where you create the Loan object and see if that might be the case.
Also why do you have to get a reference to the context via fetchedResultsController if you already have a declared property for it in self.managedObjectContext ?
The other thing is why do you need to call the fetchedResultsController to performFetch: again when you create a new Loan object? Is your data presented in a table view and have you implemented the NSFetchedResultsController delegate methods?
That call seems unnecessary and it may be causing issues with the cache created by the fetch. See section "Modifying the fetch request" under this link http://developer.apple.com/library/ios/documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40008227-CH1-SW24
Finally, try your delete operation directly in the view controller that received the action rather than pass it to the delegate (just to eliminate the possibility that something has been dealloc'd without you knowing).
Here's what I'd do:
- (IBAction)cancel:(id)sender
{
NSError *error;
NSManagedObjectContext *context = [self.loan managedObjectContext];
[context deleteObject:self.loan];
if (![context save:&error])
NSLog (#"Error saving context: %#", error);
}
I got a Bad Access because a deallocated UIViewController was a delegate of a NSFetchedResultsController it had.
The NSFetchedResultsController was deallocated - but when settings a delegate, it observes NSManagedObjectContext for changes, so when NSManagedObjectContext was saved - a bad access would occur when trying to notify the NSFetchedResultsController about the change.
Solution is to clear delegate of NSFetchedResultsController upon deallocation.
- (void)dealloc {
fetchedResultsController.delegate = nil;
}

Memory leak problem, could someone explain what this mean?

I am getting a memory leak on the following code line:
The code-line:
NSArray *fetchedObjects = [qContext executeFetchRequest:fetchRequest error:&error];
I have been trying to read-up on this and have tried to find the cause of this for quite some time, without success.
Could someone give me a hint where to look? ...and do i understand the "100%" correctly that it indicate that this code line is 100% causing the leak?
UPDATE
Some more code:
//=========PREPARE CORE DATA DB===========//
if (managedObjectContext == nil) { managedObjectContext = [(FamQuiz_R0_1AppDelegate *)
[[UIApplication sharedApplication] delegate] managedObjectContext]; }
// Define qContext
NSManagedObjectContext *qContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"questions" inManagedObjectContext:qContext];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [qContext executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *info in fetchedObjects) {
if ([[info valueForKey:#"qDiff"] intValue] == 1) {
[allEasyArrayQ addObject:[info valueForKey:#"idQ"]];
} else if ([[info valueForKey:#"qDiff"] intValue] == 2) {
[allMediumArrayQ addObject:[info valueForKey:#"idQ"]];
} else if ([[info valueForKey:#"qDiff"] intValue] == 3) {
[allHardArrayQ addObject:[info valueForKey:#"idQ"]];
}
}
You are probably over-retaining the array or the objects inside it later in this method or even outside of this method. The line will only indicate where the objects are created, not where the actual extra retain is performed. For that you'd need to check using Instruments which call stacks retain and release the leaked objects.
No, the 100% means that this leak accounts for 100% of your leaked memory (ie, this is you only leak).
Note if you want to fix the leak you are looking in the wrong place. Leaks tells you which instance is leaking, it's Class and it's memory management history. Try a tutorial like this one http://www.cimgf.com/2008/04/02/cocoa-tutorial-fixing-memory-leaks-with-instruments/
Note, what Leaks can't tell you is the line where you are leaking, as the cause of your leak is something you haven't done, as opposed to something you have done (ie you didn't release your object).

MBProgressHUD altering data output?

I'm trying to use MBProgressHUD to show a loading animation while I'm accessing information to smooth out the process of going from a UITableView listing to a UIWebView that has detailed information of the item selected. If I call [self fetchPlayer]; without using MBProgressHUD I have no issues and everything works fine albeit without the animation. But if I call [self loadingAnimation]; it half works. The first time I select something from the UITableView it loads correctly every time, but if I go back and select the same or different item I will quite often get null values for playerDetails items. I'm not sure what the MBProgressHUD method could be doing to cause this but here is the code. The NSLog is displaying the correct information - but the main class that is calling the two methods does not output it correctly.
- (void)loadingAnimation {
// The hud will dispable all input on the view (use the higest view possible in the view hierarchy)
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
// Add HUD to screen
[self.navigationController.view addSubview:HUD];
HUD.labelText = #"Loading";
// Show the HUD while the provided method executes in a new thread
[HUD showWhileExecuting:#selector(fetchPlayer) onTarget:self withObject:nil animated:YES];
}
- (void)fetchPlayer {
NSManagedObjectContext *pcontext = [[AppController sharedAppController] managedObjectContext];
NSFetchRequest *pfetch = [[NSFetchRequest alloc] init];
NSEntityDescription *pentity = [NSEntityDescription entityForName:#"Players"
inManagedObjectContext:pcontext];
[pfetch setEntity:pentity];
NSPredicate *ppredicate = [NSPredicate predicateWithFormat:#"playerID=%#", [playerNews playerID]];
[pfetch setPredicate:ppredicate];
NSError *perror;
NSArray *plist = [pcontext executeFetchRequest:pfetch error:&perror];
playerDetails = [plist objectAtIndex:0];
NSLog(#"%# %# %# %# %#", [playerNews playerID],
[playerDetails valueForKey:#"playerFirstName"],
[playerDetails valueForKey:#"playerLastName"],
[playerDetails valueForKey:#"position"],
[playerDetails valueForKey:#"dateOfBirth"]);
[pfetch release];
NSManagedObjectContext *context = [[AppController sharedAppController] managedObjectContext];
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Teams"
inManagedObjectContext:context];
[fetch setEntity:entity];
if (![playerDetails valueForKey:#"team"]) {
team = [playerDetail team];
} else {
team = [playerDetails valueForKey:#"team"];
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"team=%#", team];
[fetch setPredicate:predicate];
NSError *error;
NSArray *list = [context executeFetchRequest:fetch error:&error];
playerTeam = [list objectAtIndex:0];
[fetch release];
}
This seems to be at least a problem with threading. You are sharing your context across multiple threads as fetchPlayer is executed in a background thread by MBProgressHUD.
Create a new Context in the background thread and make sure NSManagedObjects are not shared across threads.

iPhone: Code works in 3G but not 3GS

I've got a REALLY strange problem - my testers report problems (app is hanging, not crashing) on 3GS, but NOT on 3G... this is the code where I'm assuming the problem:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
[FlurryAPI startSession:#"myflurryapisessionkey"];
[FlurryAPI setSessionReportsOnCloseEnabled:NO];
// set managedObjectContext on TabBarController
tabBarController.managedObjectContext = self.managedObjectContext;
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
// check if we have to show a favorite immediately
Favorite *startseiteFavorite = [self getStartSeiteFavorite];
if (startseiteFavorite != nil) {
[FlurryAPI logEvent:#"favorite found"];
[self showStartseiteFavorite:startseiteFavorite];
} else {
[FlurryAPI logEvent:#"no favorite found"];
}
}
- (Favorite *) getStartSeiteFavorite {
// loading values
smart_infoAppDelegate *appDelegate = (smart_infoAppDelegate *)[[UIApplication sharedApplication] delegate];
managedObjectContext = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Favorite" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSPredicate * predicate;
predicate = [NSPredicate predicateWithFormat:#"startseite == 1"];
[request setPredicate:predicate];
NSError *error;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
[request release];
Favorite *tempFavorite = [mutableFetchResults count] > 0 ? [mutableFetchResults objectAtIndex:0] : nil;
[mutableFetchResults release];
return tempFavorite;
}
I'd like to select a tab according to select the tab according to the existence of such a 'startseiteFavorite' - if there's one, I select tab 1, otherwise tab 0... does anyone of you find a problem or a reason why this works without problems in 3G but not in 3GS?
Thanks a lot,
Stefan
It's pretty tough to figure out a problem like this if you have not actually duplicated the problem yourself? Are you not able to duplicate the problem on the 3GS? You're saying that you are assuming where the problem occurs. That's not the best approach.
Do you not have a 3GS to test on? If not, I would go buy one to test it and get to the bottom of the issue directly in the debugger. You should never ship an app without having the hardware your app says it supports (not sure if you're doing that, but I'm thinking it's possible from the sound of your question).
Ask your testers exactly how they are causing the hang to occur.

app crashes when releasing appDelegate instance

i have this code that passes the core data context to one of the controllers.
it was working great for few days, until the debugger started to give me the "not A type release" error and crashing the app.
i have checked the app for leaks and i found leaks from the SappDelegate object. so i understand that i have to release it but it keeping crashing every time i do it.
any ideas
thanks
shani
SAppDelegate *hbad= [[SAppDelegate alloc] init];
NSManagedObjectContext *context = [hbad managedObjectContext];
[hbad release];
if (!context) {
NSLog(#"problem with mannaged");
}
self.managedObjectContext = context;
If SAppDelegate is your actual app delegate, that is not the correct way to get it. you should change your code to:
SAppDelegate *hbad= [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [hbad managedObjectContext];
if (!context) {
NSLog(#"problem with mannaged");
}
self.managedObjectContext = context;
Also, leaks will not cause crashes until MUCH later when your application runs out of memory and the system kills it.
I'm not entirely sure why you're creating a new SAppDelegate. You should only have one of these and it gets created for you on startup. Why do you need another SAppDelegate instance?
You should see Elfred's answer to get the app delegate instead of creating one.
However, there is one bug in the code you have posted . . .
You need to retain the context until you're done with it. Either :
SAppDelegate *hbad= [[SAppDelegate alloc] init];
NSManagedObjectContext *context = [[hbad managedObjectContext] retain];
[hbad release];
if (!context) {
NSLog(#"problem with mannaged");
}
self.managedObjectContext = context;
[context release];
or release hbad later on :
SAppDelegate *hbad= [[SAppDelegate alloc] init];
NSManagedObjectContext *context = [hbad managedObjectContext];
if (!context) {
NSLog(#"problem with mannaged");
}
self.managedObjectContext = context;
[hbad release];