Question

The following code is from Apple's Core Data template, but I've seen similar code from many different developers:

- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
             // Replace this implementation with code to handle the error appropriately.
             // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        } 
    }
}

Why is there a new object created for the managedObjectContext? Why is self.managedObjectContext not sufficient. Personally, I would have used just that.

What is the logic behind copying a property into a fresh, local variable when you could simply use the property?

Was it helpful?

Solution 2

A. As mentioned in the comment to your Q, there is no new object. You should really understand the difference between (Objective-C) object and object pointer. In my books I usually use code like below to explain that:

// Copy reference
NSMutableString *ref1 = [@"Amin" mutableCopy];
NSMutableString *ref2 = ref1;

[ref1 appendString:@" Negm"];
NSLog( @"%@ / %@", ref1, ref2 );

You will get

$ Amin Negm / Amin Negm

What? Both objects changed? No, there is only one object and two pointers to it. If you change the one object using one pointer it is the one changed object even you address it using the second pointer. I. e. this is the semantically difference between strong and copy for declared properties.

To have two objects, you have to explicitly copy the first object:

// Copy reference
NSMutableString *ref1 = [@"Amin" mutableCopy];
NSMutableString *ref2 = [ref1 mutableCopy];

[ref1 appendString:@" Negm"];
NSLog( @"%@ / %@", ref1, ref2 );

In this case the object ref1 points to is copied, so we have two objects, and then the reference to the new object is assigned to ref2. In this case you have two different objects and you will get the expected result:

$ Amin Negm / Amin 

B. Why should one assign the reference to a new var? Beside the reason mentioned in Logan's answer (which is not sufficient in this case, we are talking about saving, that means disk access and a method invocation does not change the performance in a relevant way), there is a different reason: Code readability

1: Using a second reference var has the advantage that the code is more compact. It is simply shorter and easier to overlook.

2: Using a second reference var has the advantage that you get a new label. Using var names like oldContext and newContext or backgroundContext and mainContext or $whatever makes it easy to the reader to follow the data flow in a complex algorithm.

OTHER TIPS

I think it's because when you call self.managedObjectContext you're really calling [self managedObjectContext]

By assigning it to a variable temporarily, we can use the value without cycling through the code over and over again. Most of the time, it probably won't be a huge issue, but in general, it is probably a touch faster.

Otherwise, you'd have to do

if (self.managedObjectContext != nil) {
    if ([self.managedObjectContext hasChanges] && ![self.managedObjectContext save:&error]) {
         // Replace this implementation with code to handle the error appropriately.
         // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    } 
}

which calls [self managedObjectContext] 3 times instead of 1

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top