带参数iOS的单例

我需要实现一个接受参数的单例类。 同一个对象将作为一个参数每一次传递,所以得到的单例对象将永远是相同的。

我正在做类似下面的代码。 这看起来好吗? 有没有更好的方法来实现我想达到的目标?

- (id)sharedInstanceWithAccount:(UserAccount *)userAccount { if (!sharedInstance) { @synchronized(self) { sharedInstance = [[[self class] alloc] initWithAccount:userAccount]; } } return sharedInstance; } - (id)initWithAccount:(UserAccount *)userAccount { self = [super init]; if (self) { _userAccount = userAccount; } return self; } - (id)init { NSAssert(false, @"You cannot init this class directly. It needs UserAccountDataSource as a paramter"); return nil; } + (id)alloc { @synchronized(self) { NSAssert(sharedInstance == nil, @"Attempted to allocated a second instance of the singleton"); sharedInstance = [super alloc]; return sharedInstance; } return nil; } 

在这个devise中有一些问题:

  1. 正如苹果推荐的,应该为dispatch_once而不是@synchronized(self) for singleton:

     static MyClass *sharedInstance = nil; static dispatch_once_t onceToken = 0; dispatch_once(&onceToken, ^{ sharedInstance = [[MyClass alloc] init]; // Do any other initialisation stuff here }); return sharedInstance; 

    请参阅此问题以获取更多详细信息: 为什么Applebuild议使用dispatch_once来实现ARC下的单例模式?

  2. 糟糕的APIdevise把单身人士放在alloc

    如方法alloc的名称所示,这意味着将分配一些内存。 不过,就你而言,事实并非如此。 这种覆盖alloc尝试会导致团队中的其他程序员混淆。

  3. 在你的-init使用NSAssert想法不好。

    如果你想禁用一个方法,把它放在你的头文件中禁用它:

     - (id)init __attribute__((unavailable)); 

    在这种情况下,您将得到一个编译错误,而不是在运行时崩溃应用程序。 请参阅此帖以获取更多详细信息: 重写Core Data属性的方法:isDeleted

    而且,你甚至可以添加不可用的消息:

     - (id)init __attribute__((unavailable("You cannot init this class directly. It needs UserAccountDataSource as a parameter"))); 
  4. 有时input参数会被忽略,而不会有任何警告。

    在下面的代码中,调用此函数的程序员如何知道input参数userAccount有时会被忽略,如果某个类的实例已经由其他人创build的话?

     - (id)sharedInstanceWithAccount:(UserAccount *)userAccount { if (!sharedInstance) { @synchronized(self) { sharedInstance = [[[self class] alloc] initWithAccount:userAccount]; } } return sharedInstance; } 

总之,不要认为用参数创build单例是一个好主意。 使用传统的单件devise是更清洁。

 objA = [Object sharedInstanceWithAccount:A]; objB = [Object sharedInstanceWithAccount:B]; 

B被忽略。 objB中的userAccount是A.

如果objB中的userAccount B,您将更改sharedInstanceWithAccount。

 - (id)sharedInstanceWithAccount:(UserAccount *)userAccount { static NSMutableDictionary *instanceByAccount = [[NSMutableDictionary alloc] init]; id instance = instanceByAccount[userAccount]; if (!instance) { @synchronized(self) { instance = [[[self class] alloc] initWithAccount:userAccount]; instanceByAccount[userAccount] = instance; } } return instance; }