最近面试的时候,面试官让我写下单例,我是如下写的
+ (Singleton *)sharedSingleton{
static Singleton *singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[Singleton alloc]init];
});
return singleton;
}但是面试官看了看说如果这样写的话是保证了线程安全,但是如果要是直接 [[Singleton alloc]init] 的话还是不能保证该对象只被创建一次,他说需要重载下+new, +alloc,+allocWithZone:, -copyWithZone:, 以及 -mutableCopyWithZone这些方法,请问真的是这样吗?给我解答下吧

解决方案 »

  1.   

    如果直接用alloc init的话必须重写父类方法,也就是这个alloc init系统方法
    +(id)allocWithZone:(struct _NSZone *)zone
    {
        if (singleton == nil) {
            singleton = [super allocWithZone:zone];
        }
        return singleton;
    }
      

  2.   

    面试官说的没错,你只是提供了一个实例的全局访问点,并不是真正的单例。真正的单例需要重载所有和创建有关的方法,如果是非 ARC,还要重载 release、retain 等方法,需要这些方法很多,但是你可以写一个宏来重载所有这些方法,一键实现单例
      

  3.   

    #import "SingleInstance.h"@interface SingleInstance ()<NSCopying,NSMutableCopying>@end//定义一个当前单例对象的一个实例,并赋值为nil
    static SingleInstance *instance = nil;@implementation SingleInstance#if 0
    //单例创建一:
    + (instancetype)sharedInstance
    {
        
        @synchronized(self)
        {
            if (!instance)
            {
                //不存在就创建当前单例对象
                instance = [[self alloc] init];
            }
            
            return instance;
        }
        
    }
    #endif//单例创建二:
    + (instancetype)sharedInstance
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [[self alloc] init];
        });    return instance;
    }//alloc会触发,防止通过alloc创建一个不同的实例
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [super allocWithZone:zone];
        });
        
        return instance;
    }- (id)copyWithZone:(nullable NSZone *)zone
    {
        return self;
    }- (id)mutableCopyWithZone:(nullable NSZone *)zone
    {
        return self;
    }//手动内存管理下写这些- (instancetype)retain
    {
        return self;
    }- (oneway void)release
    {
        
    }- (instancetype)autorelease
    {
        return self;
    }- (NSUInteger)retainCount
    {
        return MAXFLOAT;
    }- (void)dealloc
    {
        
    }@end