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?
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With