What does "Context" mean in Cocoa/Objective-c? - objective-c

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).

Related

Can a static variable used as #synchronized parameter?

We want to guarantee thread safety for a static variable.
We used another static variable as object in the #synchronized directive. Like this:
static NSString *_saveInProgressLock = #"SaveInProgressLock";
static BOOL _saveInProgress;
+ (BOOL)saveInProgress {
#synchronized(_saveInProgressLock) {
return _saveInProgress;
}
}
+ (void)setSaveInProgress:(BOOL)save {
#synchronized(_saveInProgressLock) {
_saveInProgress = save;
}
}
We are experiencing issues in the app currently on the store, which may be reproduced by preventing the _saveInProgress variable to be set to NO.
Do you see any problem with the above code?
How does it differ from this?
static BOOL _saveInProgress;
+ (BOOL)saveInProgress {
#synchronized([MyClass class]) {
return _saveInProgress;
}
}
+ (void)setSaveInProgress:(BOOL)save {
#synchronized([MyClass class]) {
_saveInProgress = save;
}
}
tl;dr: This is perfectly safe as long as the string literal is unique. If it is not unique there may be (benign) problems, but usually only in Release mode. There may be an easier way to implement this, though.
#synchronized blocks are implemented using the runtime functions objc_sync_enter and objc_sync_exit (source). These functions are implemented using a global (but objc-internal) side table of locks that is keyed by pointer values. On the C-API-level, you could also lock on (void *)42, or in fact any pointer value. It doesn't even matter wether the object is alive, because the pointer is never dereferenced. However, the objc compiler refuses to compile a #synchronized(obj) expression if the obj does not statically typecheck to an id type (of which NSString * is a subtype, so it's okay) and maybe it retains the object (I'm not sure about that), so you should only use it with objects.
There are two critical points to consider though:
if the obj on which you synchronize is the NULL-pointer (nil in Objective C), then objc_sync_enter and objc_sync_exit are no-ops, and this leads to the undesirable situation where the block is performed with absolutely no locking.
If you use the same string value for different #synchronized blocks, the compiler may be smart enough to map them to the same pointer address. Maybe the compiler does not do this now, but it is a perfectly valid optimization that Apple may introduce in the future. So you should make sure that you use unique names. If this happens, two different #synchronized blocks may accidentally use the same lock where the programmer wanted to use different locks. By the way, you can also use [NSObject new] as a lock object.
Synchronizing on a class object ([MyClass class]) is perfectly safe and okay too.
Now for the easier way. If you just have a single BOOL variable that you want to be atomic, you may use lock-free programming:
static BOOL _saveInProgress;
+ (BOOL)saveInProgress {
__sync_synchronize();
return _saveInProgress;
}
+ (void)setSaveInProgress:(BOOL)save {
_saveInProgress = save;
__sync_synchronize();
}
This has much better performance and is just as threadsafe. __sync_synchronize() is a memory barrier.
Note however, that the safety of both solutions depend on how you use them. If you have a save-method somewhere that looks like this:
+ (void)save { // line 21
if(![self saveInProgress]) { // line 22
[self setSaveInProgress:YES]; // line 23
// ... do stuff ...
[self setSaveInProgress:NO]; // line 40
}
}
that +save method is not threadsafe at all, because there is a race condition between line 22 and line 23. (Don't wanna go into details here.. just ask a new question if you need more information.)

How to implement a reentrant locking mechanism in objective-c through GCD?

I have an objective-c class with some methods, which use a GCD queue to ensure that concurrent accesses to a resource take place serially (standard way to do this).
Some of these methods need to call other methods of the same class. So the locking mechanism needs to be re-entrant. Is there a standard way to do this?
At first, I had each of these methods use
dispatch_sync(my_queue, ^{
// Critical section
});
to synchronize accesses. As you know, when one of these methods calls another such method, a deadlock happens because the dispatch_sync call stops the current executing until that other block is executed, which can't be executed also, because execution on the queue is stopped. To solve this, I then used e.g. this method:
- (void) executeOnQueueSync:(dispatch_queue_t)queue : (void (^)(void))theBlock {
if (dispatch_get_current_queue() == queue) {
theBlock();
} else {
dispatch_sync(queue, theBlock);
}
}
And in each of my methods, I use
[self executeOnQueueSync:my_queue : ^{
// Critical section
}];
I do not like this solution, because for every block with a different return type, I need to write another method. Moreover, this problem looks very common to me and I think there should exist a nicer, standard solution for this.
First things first: dispatch_get_current_queue() is deprecated. The canonical approach would now be to use dispatch_queue_set_specific. One such example might look like:
typedef dispatch_queue_t dispatch_recursive_queue_t;
static const void * const RecursiveKey = (const void*)&RecursiveKey;
dispatch_recursive_queue_t dispatch_queue_create_recursive_serial(const char * name)
{
dispatch_queue_t queue = dispatch_queue_create(name, DISPATCH_QUEUE_SERIAL);
dispatch_queue_set_specific(queue, RecursiveKey, (__bridge void *)(queue), NULL);
return queue;
}
void dispatch_sync_recursive(dispatch_recursive_queue_t queue, dispatch_block_t block)
{
if (dispatch_get_specific(RecursiveKey) == (__bridge void *)(queue))
block();
else
dispatch_sync(queue, block);
}
This pattern is quite usable, but it's arguably not bulletproof, because you could create nested recursive queues with dispatch_set_target_queue, and trying to enqueue work on the outer queue from inside the inner one would deadlock, even though you are already "inside the lock" (in derision quotes because it only looks like a lock, it's actually something different: a queue — hence the question, right?) for the outer one. (You could get around that by wrapping calls to dispatch_set_target_queue and maintaining your own out-of-band targeting graph, etc., but that's left as an exercise for the reader.)
You go on to say:
I do not like this solution, because for every block with a different
return types, I need to write another method.
The general idea of this "state-protecting serial queue" pattern is that you're protecting private state; why would you "bring your own queue" to this? If it's about multiple objects sharing the state protection, then give them an inherent way to find the queue (i.e., either push it in at init time, or put it somewhere that's mutually accessible to all interested parties). It's not clear how "bringing your own queue" would be useful here.

keyPathsForValuesAffectingValueForKey: does it trigger changes recursively?

I'm reading the Key-Value Observing guide from Apple, and it hasn't explained one point in detail.
My question is: say I have a name property that's dependent on firstName and lastName, and I also have another property group that's dependent on name and gender.
Following the guide, I've written this
+ (NSSet *)keyPathsForValuesAffectingName {
return [NSSet setWithObjects:#"lastName",#"firstName",nil];
}
When writing the corresponding method for group, can I write it like this
+ (NSSet *)keyPathsForValuesAffectingGroup {
return [NSSet setWithObjects:#"name",#"gender",nil];
}
Or I have to add all the related properties
+ (NSSet *)keyPathsForValuesAffectingGroup {
return [NSSet setWithObjects:#"firstName",#"lastName",#"gender",nil];
}
Note that both group and name are computed, readonly properties.
If your questions means ...
Can keyPathsForValuesAffecting<key> be chained to indirectly affect keys through several dependant properties?
... then the answer is yes.
Edit: Apple's documentation on keyPathsForValuesAffectingValueForKey: confirms support for indirect dependent notifications.
Your last comment seems to suggest that you expect KVO notifications (indirect or not) being sent when directly changing an ivar. That's not the case. KVO relies on using the proper setter or on manually announce the change by sending will/didChangeValueForKey:
I'm pretty sure, that this will work, because it would be hard to let it not work.
Let us imagine, that you have three external (= different objects) observers for the properties.
What happens:
A. The opening door for KVO is a message didChangeValueForKey: to the observed object. If you have turned on automatic KVO, this message is sent automatically, when the setter for the key is called. (This is done in a dynamic generated subclass, which overwrites the setter.)
B. Then KVO code is triggered that looks semantically like this: (And it is simplified for only supporting keys, but not key paths.)
NSSet *observers = kvoBucket[key];
for( id observer in observers )
{
[observer observeValue:[self valueForKey:key] forKeyPath:key …]
}
C. With affecting keys there has to be a second loop, informing about a change of the depending properties. (I assume, that this list is generated at the initialization of the class' object or adding the observation.)
// Inform observers
NSSet *observers = kvoBucket[key];
for( id observer in observers )
{
[observer observeValue:[self valueForKey:key] forKeyPath:key …]
}
// Scan for affected properties
NSSet *keyOfaffectedProperties = affectedPropertiesBucket[key];
for( NSString *key in keyOfaffectedProperties )
{
// trigger kvo for affected property
}
No let us sit down on the developer's chair. He can duplicate the first loop into the second loop. In this case it would not work. But this is duplicate code. (And the real code is more complicated for sure.) Why should he do that? Everyone of us would say: I already have this code! Let's use it again:
- (void)informOberserversForChangeOfKey:(NSString*)key
// Inform observers
NSSet *observers = kvoBucket[key];
for( id observer in observers )
{
[observer observeValue:[self valueForKey:key] forKeyPath:key …]
}
// Scan for affected properties
NSSet *keyOfaffectedProperties = affectedPropertiesBucket[key];
for( NSString *keyOfAffectedProperty in keyOfaffectedProperties )
{
[self informObserversForChangeOfKey:keyOfAffectedProperty];
}
If there is no optimization, which makes recursion impossible or inconvenient, it should work. I would bet it works – But only a small amount of money. ;-)
Most people here have got the right idea but to confirm this I've set up a test project with exactly the same code mentioned in my question.
And the result: it works for both ways.

Obj-C introspection: how to avoid casting all the time?

Hello all,
I've been working on some enumeration routines in Objective-C that perform object introspection. In particular, I'm fast enumerating an NSSet and making sure that the objects therein belong to class BBBallView (an fairly unfortunate name, I agree) before tweaking their properties and/or calling their methods.
In order to make the parser and compiler happy, however, I end up casting the object to its class on every single line; moreover, in order to access its properties, the object's cast has to be in parentheses, otherwise dot notation won't work. This leads to somewhat messy code:
for (id otherBall in self.gameField.subviews) {
if ([otherBall isKindOfClass:[BBBallView class]]) {
if ( !((BBBallView *)otherBall).isEnlarged ) {
CGRect otherFrame = ((BBBallView *)otherBall).frame;
/* ... */
}
}
}
Is there any way to tell the compiler something like "at this point I know that otherBall is a BBBallView, so stop telling me it doesn't respond to these selectors and properties"? That way, one could just write:
for (id otherBall in self.gameField.subviews) {
if ([otherBall isKindOfClass:[BBBallView class]]) {
if ( !otherBall.isEnlarged ) {
CGRect otherFrame = otherBall.frame;
/* ... */
}
}
}
and so on.
I tried otherBall = (BBBallView *)otherBall but "fast enumeration variables can't be modified in ARC by default". Changing the enumeration variable to __strong id fixes it, but doesn't help the fact that any subsequent line gives out errors such as "property isEnlarged not found on object of type 'const __strong id'", so I'm back to square one.
I'm not even sure why exactly this happens: shouldn't the compiler stay out of the way when an variable is of type id? In any case, the whole ordeal particularly messy in methods that need to perform several calculations on objects' properties, as it quickly becomes unreadable with all those parentheses.
Is there any way around this?
Thanks in advance!
You can either create a local temp with the correct type or just not use dot notation.
local temp
for (UIView *view in self.gameField.subviews) {
if ([view isKindOfClass:[BBBallView class]]) {
BBBallView *ballView = view;
if (!ballView.isEnlarged) {
CGRect otherFrame = ballView.frame;
/* ... */
}
}
}
don't use dot notation
for (id otherBall in self.gameField.subviews) {
if ([otherBall isKindOfClass:[BBBallView class]]) {
if ( ![otherBall isEnlarged]) {
CGRect otherFrame = [otherBall frame];
/* ... */
}
}
}
If I was only doing a couple of things I would be tempted to not use dot notation. If it became awkward to read and there was a lot of accesses then I would consider local temp
I think you're struggling because the logic appears misplaced. The language is fighting you because of your program's structure, not because the language is deficient.
Is the parent type of subviews really appropriate? Or are you violating the Liskov Substitution Principle by stuffing a round object in a square type?
You can also ask if is it really appropriate to examine the internals of BBBallView logic from outside? Can you move the logic into the appropriate class?

Where is the retain count stored for NSObjects in Objective C

I am curious about how retain/release work internally. On the face, it seems like there's an integer related to each instance of an NSObject, which gets increased and decreased when you call -retain and -release, respectively.
But taking a look at NSObject, the only instance variable it has is the isa variable, for determining its class type.
So where are retain counts for individual objects stored? Not that I'm going to muck around with it, but just for my own edification.
Is it stored with the NSObject, but hidden away in some Objective C implementation detail? If so, that seems like a bad design to me. One should be able to create their own root class and handle their own retain/release counting in a similar fashion (not that it's a good idea--one would have to have a very good reason not to use NSObject).
The storage location for the retain count depends on both the runtime in use and the class implementation.
For Apple's Objective-C runtime, you can figure out a lot by digging into the source code of the Objective-C runtime.
For example, if you're using ARC (and I think even if you're not), the reference counts for most objects are stored in hash tables. Have a look at the _objc_rootRetain function in runtime/objc-arr.mm. I don't know exactly why they did this. Perhaps it's a way of keeping retain counts together for better cache behavior (which is important under ARC because ARC adjusts retain counts more often than non-ARC code usually does).
However, some classes override retain and related methods and store the retain count elsewhere. For example, when debugging a memory leak I discovered that CALayer does this. Instead of using the runtime's normal retain count mechanism, a CALayer stores its retain count in a private C++ implementation object. This is rather frustrating because it means the Instruments Allocations instrument doesn't log retains and releases of CALayer objects.
We do not know exactly how the data is stored, but we can rule out a few options:
Private Implementation Variables
We can rule this out, simply because when we iterate through the iVars of the NSObject class, we see only one: isa, as shown through this program:
id object = [NSObject new];
Class meta = object->isa;
printf("class name: %s\n", class_getName(meta));
unsigned count;
Ivar *ivars = class_copyIvarList(meta, &count);
for (int i = 0; i < count; i++) {
printf("iVar: %s\n", ivar_getName(ivars[i]));
}
free(ivars);
And note that even private implementation properties exist in the class metdata.
Private Properties
We can also rule this out, as even private properties are exposed in the classes metadata, as shown by the following example, there are no properties for the NSObject class:
id object = [NSObject new];
Class meta = object->isa;
printf("class name: %s\n", class_getName(meta));
objc_property_t *properties = class_copyPropertyList(meta, &count);
for (int i = 0; i < count; i++) {
printf("property: %s\n", property_getName(properties[i]));
}
Associated Objects
This one is very hard to rule out, as there are no direct ways to get a list of all the associated objects. However, since the concept of associated objects is very new, and reference counting has been around forever, I say that this is not very likely.
CoreFoundation struct-mangling
This is my best guess. When you create a NSObject, it is a struct behind the scenes. What is to say that the actual NSObject data representation is something like this:
typedef struct CFObject {
int retainCount;
id isa;
} *CFObjectRef;
Then, when an object is created:
id object_createInstance(...)
{
CFObjectRef object = malloc(sizeof(struct CFObject));
...
return (id) (object + sizeof(object->retainCount));
}
int object_retainCount(id self)
{
CFObjectRef asObject = (CFObjectRef) (self - sizeof(asObject->retainCount));
return asObject->retainCount;
}
I cannot verify this however, as there are many other ways this could be done (a map of integers to objects, for example).
It doesn't sound like it, but just in case... if you're thinking of using retain count directly, don't.
As for implementation details, sessions at WWDC 2011 mentioned that under ARC, most of the reference counting implementation has moved into the ObjC runtime. Source for that is available, so you might be able to find out for yourself how it works. For manual reference counting, much of the ObjC behaviors are replicated in CoreFoundation and libdispatch, which are also open source -- if you're looking to implement a similar scheme yourself, those might prove educational.
In general, this is an implementation detail for the same reason many things are: encapsulation is good policy, especially for framework providers. You don't want users of a framework depending on implementation details because then you can't change your implementation without breaking their code.
Don't know if this would be relevant, but I've stumbled upon the blog post about higher order messages implementation in the Objective-C. There author implements the HOM object as a root class (i.e. not inherited from NSObject) and the implementation looks like this:
#interface HigherOrderMessage {
Class isa;
NSUInteger retainCount;
//not relevant to this question part
}
Then the retain count managing methods are implemented like this:
- (id)retain {
__sync_add_and_fetch(&retainCount, 1);
return self;
}
- (id)autorelease {
[NSAutoreleasePool addObject:self];
return self;
}
- (void)release {
if (__sync_sub_and_fetch(&retainCount, 1) == 0) {
[methodSignatureForSelector release];
[forward release];
object_dispose(self);
}
}
This code actually works, so although we do not know how exactly the retainCount is implemented in the Cocoa classes, it is certain that it could be implemented in some similar way.
For addition insight, check out http://www.mikeash.com/pyblog/friday-qa-2011-09-16-lets-build-reference-counting.html, where Mike Ash explores an alternative implementation like the one Apple uses.