views:

914

answers:

3

I've found this snippet of code on the net. It sets up an NSMutableArray in a way I've not seen before ( I'm an Obj-C newb). Can someone explain what it's doing and why you would do it this way? Particularly the @syncronized, static and little plus sign on the method signature.

add the following to the .h file:
+(NSMutableArray *)allMySprites;

add the following to he .m file after implementation:

static NSMutableArray * allMySprites = nil;

+(NSMutableArray *)allMySprites {
    @synchronized(allMySprites) {
        if (allMySprites == nil)
            allMySprites = [[NSMutableArray alloc] init];
        return allMySprites;
    }
 return nil;

}

+1  A: 

The + sign indicates the method is static as opposed to instance methods. It means the method belongs to the class rather than each instance of a class (just like static things in Java and C#). @synchronized acquires a lock on the object specified (like lock statement in C#). It means no other thread can enter a @synchronized block with that object.

The code as a whole is trying to initialize a singleton collection the first time (when it's not initialized yet) and cache it for use in subsequent calls to that method. The synchronized block creates a critical section to make the initialization part safe in case of a race condition where two threads try to get the value roughly the same time while it's still doing the initialization.

Mehrdad Afshari
+1  A: 

It's an implementation of the Singleton design pattern, basically a way of making sure that you only have one copy of your MySprites.

The details:

  • The + means that this is a class method
  • The @syncyronize makes access to the allMySprites variable thread-safe (there are a few caveats but that's the one line summary)
  • I believe that the static limits the scope of the variable only to the file
Stephen Darlington
+2  A: 

Adding to the other responses ... the posted code is wrong. It should be more like this:

@implementation SpriteManager
+ (NSMutableArray*) allMySprites {
    @synchronized(self) {
        if (allMySprites == nil) {
            allMySprites = [[NSMutableArray alloc] init];
        }
    }
    return allMySprites;
}
@end

It makes no sense to @synchronize on nil. Using self in a class method refers to the class and not the instance. Also the 'return nil' in the original code is pointless.

A better approach where the @synchronized can be completely avoided is to use a class initializer method:

@implementation SomeClass
+ (void) initialize
{
    allMySprites = [[NSMutableArray alloc] init];
}
@end

The initialize methods are guaranteed to be called before the class is used.

St3fan
+1 for noticing it
Mehrdad Afshari
+initialize can be called more than once if you have subclasses. It’s best to check that you’re actually initializing your class like so: if (self == [SpriteManager class]) { allMySprites = [[NSMutableArray alloc] init]; }
Ben Stiglitz