0

I'm having trouble saving to one variable letsMeet.startTimeLabel. Right after selecting NSLog shows the correct Value, however, after I save to another variable (letsMeet.endTimeLabel), letsMeet.startTimeLabel changes to (NULL). Below is the code:

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
letsMeet = (LetsMeet *) [NSEntityDescription insertNewObjectForEntityForName:@"LetsMeet" inManagedObjectContext:managedObjectContext];
switch (actionSheet.tag)
{
    case 1:
    {
        if (buttonIndex == 0)
        {
            UIDatePicker *startDatePicker = (UIDatePicker *)[actionSheet viewWithTag:kDatePickerTag1];

            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
            [dateFormatter setDateFormat:@"dd"];
            NSDate *selectedDate = [startDatePicker date];

            NSDateFormatter *dayFormatter = [[NSDateFormatter alloc] init];
            [dayFormatter setDateFormat:@"EEEE"];
            NSDate *selectedDay= [startDatePicker date];

            NSDateFormatter *monthFormatter = [[NSDateFormatter alloc] init];
            [monthFormatter setDateFormat:@"MMMM"];
            NSDate *selectedMonth = [startDatePicker date];

            NSString *date = [[NSString alloc] initWithFormat:@"%@", [dateFormatter stringFromDate:selectedDate]];
            DateLabel.text = date;
            [letsMeet setDateLabel:date];

            NSString *month = [[NSString alloc] initWithFormat:@"%@", [dayFormatter stringFromDate:selectedMonth]];
            MonthLabel.text = month;
            [letsMeet setMonthLabel:month];

            NSString *day = [[NSString alloc] initWithFormat:@"%@", [monthFormatter stringFromDate:selectedDay]];
            DayLabel.text = day;
            [letsMeet setDateLabel:day];

            NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init];
            [timeFormatter setDateFormat: @"h:mm a"];
            NSDate *selectedStartTime = [startDatePicker date];

            NSString *startTime = [[NSString alloc] initWithFormat:@"%@", [timeFormatter stringFromDate:selectedStartTime]];
            StartTimeLabel.text = startTime;
            [letsMeet setStartTimeLabel:startTime];

            NSError *error = nil;
            if (![managedObjectContext save:&error]){

                NSLog(@"Error Saving");
            }
        }
        NSLog (@"This is the StartTime after selecting %@", letsMeet.startTimeLabel);
    }
    break;

    case 2:
    {
        if (buttonIndex == 0)
        {
            UIDatePicker *endTimePicker = (UIDatePicker *)[actionSheet viewWithTag:kDatePickerTag2];
            NSDateFormatter *endTimeFormatter = [[NSDateFormatter alloc] init];
            [endTimeFormatter setDateFormat: @"h:mm a"];
            NSDate *endSelectedTime = [endTimePicker date];
            NSString *endTime = [[NSString alloc] initWithFormat:@"%@", [endTimeFormatter stringFromDate:endSelectedTime]];
            EndTimeLabel.text = endTime;
            [letsMeet setEndTimeLabel:endTime];
            NSLog (@"This is the EndTime %@", letsMeet.endTimeLabel);
            NSLog (@"This is the StartTime after selecting BOTH %@", letsMeet.startTimeLabel);
        }
        else if (buttonIndex == 1)
        {
            EndTimeLabel.text = @"Whenever";
            [letsMeet setEndTimeLabel:EndTimeLabel.text];
        }
        NSError *error = nil;
        if (![managedObjectContext save:&error]) {
    }

}break;

    // Handle the error.
}

}


-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    UIViewController *destinationViewController = segue.destinationViewController;
    NSLog (@"Prepare For Segue StartTime %@", letsMeet.startTimeLabel);
    NSLog (@"Prepare For Segue EndTime%@", letsMeet.endTimeLabel);
}

Here is the log:

2013-02-20 21:38:24.253 AppointmentTime[3129:c07] This is the StartTime after selecting 9:30 AM
2013-02-20 21:38:32.325 AppointmentTime[3129:c07] This is the EndTime 12:15 PM
2013-02-20 21:38:32.325 AppointmentTime[3129:c07] This is the StartTime after Selecting BOTH (null)
2013-02-20 21:38:34.069 AppointmentTime[3129:c07] Prepare For Segue StartTime (null)
2013-02-20 21:38:34.069 AppointmentTime[3129:c07] Prepare For Segue EndTime12:15 PM

Q: Why would letsMeet.startTimeLabel show up correct the first time and after selecting EndTime, it changes to NULL. Please note EndTime continues to show the correct Value all the way up to prepareForSegue. Weird!

user1107173
  • 10,334
  • 16
  • 72
  • 117
  • Because they are different instances. – Rog Feb 21 '13 at 05:29
  • What do you mean? I also did NSLog for both variables in PrepareForSegue as well, and StartTime shows up as NULL while EndTime shows up with the correct value. I updated the code and the Log. – user1107173 Feb 21 '13 at 05:40

1 Answers1

1

According to your logs and code , you are entering the switch block twice. Which means you are entering the actionSheet:clickedButtonAtIndex: method twice. So each time you enter the method

letsMeet = (LetsMeet *) [NSEntityDescription insertNewObjectForEntityForName:@"LetsMeet" inManagedObjectContext:managedObjectContext];

statement is executed twice, in turn creating two objects. You can see this by doing a fetch from the store.

So you are checking for properties in two different objects and hence the null.

If you are using just one managed object, you can probably add a check for nil for the object before executing insertNewObjectForEntityForName:inManagedObjectContext:. This will make sure you are using the same object.
If you are using more than one object at the same time use the object id or some unique key to identify your object and manipulate it.

Edit:
You can check for nil with the following code:

if(letsMeet==Nil){
    letsMeet = (LetsMeet *) [NSEntityDescription insertNewObjectForEntityForName:@"LetsMeet" inManagedObjectContext:managedObjectContext];
}

This will work only, if the object you are calling the actionSheet:clickedButtonAtIndex: method is always in memory. But since you are persisting you might want to fetch the object from the store and then check for no. of objects.

NSError *error;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"LetsMeet" inManagedObjectContext:managedObjectContext]];
NSArray *objectArray = [managedObjectContext executeFetchRequest:request error:&error]
if(objectArray.count==0){
    letsMeet = (LetsMeet *) [NSEntityDescription insertNewObjectForEntityForName:@"LetsMeet" inManagedObjectContext:managedObjectContext];
}else{
    letsMeet = (LetsMeet *)[objectArray objectAtIndex:0];
}

Note: If you need to persist only a couple of variables, core-data might be an overkill. Use NSUserDefaults instead and keep it simple.

Rakesh
  • 3,370
  • 2
  • 23
  • 41
  • Thank you for your reply. I'm only using one managedObject. Can you please give me an example on how to check for nil to ensure that I'm using the same managedObject and where would I put it? – user1107173 Feb 21 '13 at 06:45
  • I tried to check for the nil, but it doesn't work. I did an NSLog in that if statement and it never gets executed. NSLog for StartTime and EndTime both appear to be NULL. I then tried your fetch code. And same thing happens. NSLog inside the if statement also never gets executed. Not sure why it's skipping the over the if statement. I even tried moving both codes inside ViewDidLoad and got the same results. Should I try using ObjectID? I'm not sure how to get the unique ObjectID. Thanks – user1107173 Feb 22 '13 at 16:59
  • I also tried moving ONLY the following line to ViewDidLoad: letsMeet = (LetsMeet *) [NSEntityDescription insertNewObjectForEntityForName:@"LetsMeet" inManagedObjectContext:managedObjectContext]; and I got the following log: 2013-02-22 09:01:14.632 AppointmentTime[3140:c07] This is the StartTime after selecting 9:01 AM 2013-02-22 09:01:18.409 AppointmentTime[3140:c07] This is the EndTime 12:01 PM 2013-02-22 09:01:18.410 AppointmentTime[3140:c07] This is the StartTime after Selecting BOTH (null) – user1107173 Feb 22 '13 at 17:03
  • Sorry. there is a mistake in the solution provided.. its not letsMeet !=Nil.. but letsMeet == Nil. If the variable is nil, then only create the object. I'll update the answer. – Rakesh Feb 22 '13 at 18:49
  • and in the fetch part if it doesn't the 'if' block then it means the object array count is not zero. So you already have an object. So use that object. Again updated in the answer. – Rakesh Feb 22 '13 at 18:52
  • Since your 'insertNewObject..' statement was executed many times previously you probably have a lot of objects saved in your store. objectArray.count will give you how many. Anyway loop through objectArray and print out the objects, you will get a better idea. And since you need only one object there is no need to use objectId. You can always use the first object in the array. – Rakesh Feb 22 '13 at 18:57
  • Thank you @Rakesh! That was beautiful. Both solutions worked! I have marked the question as answered. Right now, I'm passing the reference to the same object through PrepareForSegue. I see how are you accessing the object through an array. Just for my own knowledge, how would you I get the unique ObjectID so the next few scenes can save to the same object (different variables in the entity). i.e. letsMeet.otherAttributesInTheEntity. If you like I can start a new question on StackOverflow so that you can get credit for answering? Thank you again for your help. – user1107173 Feb 23 '13 at 00:07
  • No need for that. There is a property called objectId for NSManagedObject. You can use that. And for the requirement you told objectId is still not required as the index of the fetched objects doesn't change as long as no deletion of object happens. If you found the answer useful give an up vote, no need for raising another question unless your doubt is not cleared. :-) – Rakesh Feb 23 '13 at 05:32
  • I have a related question that you may know the answer to and earn credit. Thanks. http://stackoverflow.com/questions/15125734/saving-and-deleting-nsmanagedobject-nsmanagedobjectcontext – user1107173 Feb 28 '13 at 01:16