This is UniqueInstance.m in view mode; [Download] [Up]
/******************************************************************************
.../UniqueInstance.m
Copyright Michael T. H. Scott, 1995.
UniqueInstance is a class which can have only one instance. Alloc, copy and free return error.
NOTE InterfaceBuilder uses _zoneAlloc() to create an instance of a custom object. It does not call +alloc. By overriding _zoneAlloc() for classes which respond to +uniqueInstance we guarantee that only one instance is ever allocated. It is necessary to remember that if multiple instances of a UniqueInstance subclass are included in an application's nib files then -init will be multiply called on that instance.
******************************************************************************/
#import "UniqueInstance.h"
#import <objc/objc-runtime.h>
static id uniqueInstances = nil;
static id initialized = nil;
static const char *msg = "does not %s.\n";
static id (*runtimeZoneAlloc)();
static id uniqueInstanceZoneAlloc(Class aClass,
unsigned int indexedIvarBytes,
NXZone *zone);
@implementation UniqueInstance
/*-----------------------------------------------------------------------------
Initializes the HashTable which will contain the unique instance for each UniqueInstance subclass.
-----------------------------------------------------------------------------*/
+ initialize
{
if ( self == [UniqueInstance class] )
{
uniqueInstances = [[HashTable allocFromZone: [self zone]]
initKeyDesc: "@"
valueDesc: "@"];
initialized = [[List allocFromZone: [self zone]] init];
runtimeZoneAlloc = _zoneAlloc;
_zoneAlloc = uniqueInstanceZoneAlloc;
}
return self;
}
/*-----------------------------------------------------------------------------
Returns the unique instance of the receiving class.
-----------------------------------------------------------------------------*/
+ uniqueInstance
{
const void *key = (const void *)self;
id uniqueInstance = (id)[uniqueInstances valueForKey: key];
if ( !uniqueInstance )
{
uniqueInstance = runtimeZoneAlloc(self, 0U, [self zone]);
[uniqueInstances insertKey: key value: (void *)uniqueInstance];
[uniqueInstance init];
[initialized addObject: uniqueInstance];
}
return uniqueInstance;
}
/*-----------------------------------------------------------------------------
Reimplemented to return error.
-----------------------------------------------------------------------------*/
+ alloc
{
return [self error: msg, sel_getName(_cmd)];
}
/*-----------------------------------------------------------------------------
Returns whether the receiver is uninitialized.
-----------------------------------------------------------------------------*/
- (BOOL)uninitialized
{
return [initialized indexOf: self] == NX_NOT_IN_LIST;
}
/*-----------------------------------------------------------------------------
Designated initializer.
-----------------------------------------------------------------------------*/
- init
{
if ( [self uninitialized] ) [super init];
return self;
}
/*-----------------------------------------------------------------------------
Reimplemented to return error.
-----------------------------------------------------------------------------*/
- copyFromZone: (NXZone *)aZone
{
return [self error: msg, sel_getName(_cmd)];
}
/*-----------------------------------------------------------------------------
Reimplemented to return error.
-----------------------------------------------------------------------------*/
- free
{
return [self error: msg, sel_getName(_cmd)];
}
@end
/*-----------------------------------------------------------------------------
Overrides _zoneAlloc to return the unique instance of a UniqueInstance subclasses.
-----------------------------------------------------------------------------*/
static id uniqueInstanceZoneAlloc(Class aClass,
unsigned int indexedIvarBytes,
NXZone *zone)
{
if ( [aClass respondsTo: @selector(uniqueInstance)] )
{
return [aClass uniqueInstance];
}
return runtimeZoneAlloc(aClass, indexedIvarBytes, zone);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.