2018.9.30

In iOS OC, we usually write singletons in the official recommended way:

+ (instancetype)sharedInstance {
    static URLManager * ins = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        ins = [[URLManager alloc] init];
    });
    return ins;
}
Copy the code

URLManager* a = [URLManager sharedInstance]; Now, we can use the singleton A to do a lot of things, and it doesn’t look like a problem. In many real projects, many people do.

However, who can guarantee that everyone will use the sharedInstance method to create objects? And once someone creates an object with alloc, new, etc., it’s no longer a singleton. Such as:

    URLManager* a = [URLManager sharedInstance];
    URLManager* b = [[URLManager alloc] init];
    URLManager* c = [URLManager new];
Copy the code

A, B, c:

A, B, and C are not the same object, and a singleton means that no matter how I create an object, it must be the same object

Solution 1. So how do you avoid this problem? We know that when an object is created, either alloc or new calls allocWithZone:; When you create an object with copy, the copyWithZone:, mutableCopyWithZone: method is called; Then, override these methods to make the object created unique.

+ (instancetype)sharedInstance {
    static URLManager * ins = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        ins = [[super allocWithZone:nil] init];
    });
    returnins; } + (id)allocWithZone:(NSZone *)zone{
    return [selfsharedInstance]; } - (id)copyWithZone:(NSZone *)zone{
    return [[self class] sharedInstance]; } - (id)mutableCopyWithZone:(NSZone *)zone{
    return [[self class] sharedInstance];
}
Copy the code

Run again and look at a, b, and c:

Alloc, copy, new, copy, alloc, copy, copy, alloc, copy, copy

+ (instancetype) alloc __attribute__((unavailable("replace with 'sharedInstance'"))); + (instancetype) new __attribute__((unavailable("replace with 'sharedInstance'"))); - (instancetype) copy __attribute__((unavailable("replace with 'sharedInstance'"))); - (instancetype) mutableCopy __attribute__((unavailable("replace with 'sharedInstance'")));

Copy the code

When these methods are called, an error is reported, prompting the sharedInstance method to be used: