Class tracking and instance restriction using NSSet

I would like my class to find that the new instance is equivalent (with vis isEqual: and hash) to some existing instance and creates only unique instances. Here's the code that I think does the job, but I am worried that it is doing something dumb that I cannot determine ...

Say this is a subclass of NSURLRequest:

// MyClass.h
@interface MyClass : NSMutableURLRequest
@end

// MyClass.m

@implementation MyClass

+ (NSMutableSet *)instances {

    static NSMutableSet *_instances;
    static dispatch_once_t once;

    dispatch_once(&once, ^{ _instances = [[NSMutableSet alloc] init];});
    return _instances;
}

- (id)initWithURL:(NSURL *)URL {

    self = [super initWithURL:URL];
    if (self) {
        if ([self.class.instances containsObject:self])
            self = [self.class.instances member:self];
        else
            [self.class.instances addObject:self];
    }
    return self;
}


// Caller.m
NSURL *urlA = [NSURL urlWithString:@"http://www.yahoo.com"];

MyClass *instance0 = [[MyClass alloc] initWithURL: urlA];
MyClass *instance1 = [[MyClass alloc] initWithURL: urlA];  // 2

BOOL works = instance0 == instance1;  // works => YES, but at what hidden cost?

Questions:

  • The second self assignment in init looks strange, but not crazy. Or that?
  • Is it simply desirable coding that the second alloc (instance1) gets magically cleaned up?
+5
source share
2 answers
  • , / self . ARC .

  • . № 1.

BTW, , , bbum , - . , , .

+5

( ), , URL-. , .

@interface UniqueByURLInstances:NSObject
@property(strong) NSURL *url;
@end

@implementation UniqueByURLInstances
static NSMutableDictionary *InstanceCache()
{
    static NSMutableDictionary *cache;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        cache = [NSMutableDictionary new];
    });
    return cache;
}

static dispatch_queue_t InstanceSerializationQueue()
{
    static dispatch_queue_t queue;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        queue = dispatch_queue_create("UniqueByURLInstances queue", DISPATCH_QUEUE_SERIAL);
    });
    return queue;
}

+ (instancetype)instanceWithURL:(NSURL*)URL
{
    __block UniqueByURLInstances *returnValue = nil;
    dispatch_sync(InstanceSerializationQueue(), ^{
        returnValue = [InstanceCache() objectForKey:URL];
        if (!returnValue)
        {
            returnValue = [[self alloc] initWithURL:URL];
        }
    });
    return returnValue;
}

- (id)initWithURL:(NSURL *)URL
{
    __block UniqueByURLInstances* returnValue = self;
    dispatch_sync(InstanceSerializationQueue(), ^{
        returnValue = [InstanceCache() objectForKey:URL];
        if (returnValue) return;

        returnValue = [super initWithURL:URL];
        if (returnValue) {
            [InstanceCache() setObject:returnValue forKey:URL];
        }

        _url = URL;
    });

    return returnValue;
}

- (void)dealloc {
    dispatch_sync(InstanceSerializationQueue(), ^{
        [InstanceCache() removeObjectForKey:_url];
    });
    // rest o' dealloc dance here 
}
@end

: SO - . , - . , ARC . , URL- factory, . , factory, , factory, URL- .

( URL-, NSMutableSet factory.)


, :

:

+(NSMutableSet*)instances
{
    static NSMutableSet *_instances;
    dispatch_once( ...., ^{ _instances = [[NSMutableSet alloc] init];});
    return instances;
}

, instances. +initialize ( ).

, check-allocate-or-return . dispatch_queue.

+5

All Articles