views:

124

answers:

2

Recently I've been seeing the word "context" used in method names in Cocoa, but I don't understand the meaning. I've seen it in places like Core Data (NSManagedObjectContext) and in Core Graphics (CGBitmapContextCreate) but it seems to be used all over (NSSet, NSArray, NSObject). I'm assuming that it comes from the c world.

What is this context they're talking about?

+5  A: 

It's just terminology, the contexts you mention are unrelated. The word context is usually used to describe a particular "working space".

For example, a CGContextRef or NSGraphicsContext stores a graphics space that you can perform drawing operations in.

NSManagedObjectContext stores a "working set" of NSManagedObjects for a particular persistent store.

The documentation for each API describes in detail what each of these contexts are.

Rob Keniger
kent
+1  A: 

There is no particular meaning, but there are two common ones.

First one is connected with databases, persistence layers, graphics and such beasts where you need some notion of a ‘scope’, ‘connection’ or a ‘state’. For example when saving data into a database you usually need to open the database and then save some DB ‘handle’ you will refer to in subsequent operations. There can be many different connections and thus many different ‘handles’. In other words there can be many DB contexts. Same goes for OpenGL.

Context is also used a lot in the various callback and selector passing APIs. Here it’s simply some chunk of data you would like to receive when the callback happens or the selector gets excuted. The usual use case for this is when you subscribe several times and need to tell these occasions apart:

// In one part of code not far away.
[anObject subscribeToEvent:NSObjectEventFoo withContext:@"one"];
// Somewhere else.
[anObject subscribeToEvent:NSObjectEventFoo withContext:@"two"];

// And when the callback happens:
- (void) eventFooHappenedInContext: (id) context
{
    if ([context isEqual:@"one"]) { /* something */ }
    if ([context isEqual:@"two"]) { /* something else */ }
}

The context is also used in the sorting APIs, like in the NSArray you mentioned. If you for example wanted to sort the objects according to some weight stored in a NSDictionary you could use the context to pass the weights:

NSInteger weightSort(id obj1, id obj2, void *context)
{
    NSDictionary weights = (NSDictionary*) context;
    const int weight1 = [[weights objectForKey:obj1] intValue];
    const int weight2 = [[weights objectForKey:obj2] intValue];
    if (weight1 < weight2)
        return NSOrderedAscending;
    else if (weight1 > weight2)
        return NSOrderedDescending;
    else
        return NSOrderedSame;
}

(This is a bit contrived, but I think you get the point.)

I found it interesting that the context is a lot of times simply a poor man’s solution to closures that are/were missing in the language. Because with closures you could simply pass a separate callback handler, like in JavaScript:

anObject.subscribeToEvent(eventFoo, function() { /* do something */ });
anObject.subscribeToEvent(eventFoo, function() { /* do something else */ });

This would be often more elegant than differentiating the use cases in the callback. It is now possible to do something like this in Objective-C with blocks (see tutorial by Mike Ash).

zoul
Thanks for the answer, it's brought me a little closer to understanding this topic.
nevan