Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带参数iOS的单例_Ios_Objective C_Design Patterns_Singleton - Fatal编程技术网

带参数iOS的单例

带参数iOS的单例,ios,objective-c,design-patterns,singleton,Ios,Objective C,Design Patterns,Singleton,我需要实现一个接受参数的单例类。每次都会将同一对象作为参数传递,因此生成的单例对象始终相同 我正在做下面的代码。这个看起来可以吗?有没有更好的方法来实现我想要实现的目标 - (id)sharedInstanceWithAccount:(UserAccount *)userAccount { if (!sharedInstance) { @synchronized(self) { sharedInstance = [[[self class] a

我需要实现一个接受参数的单例类。每次都会将同一对象作为参数传递,因此生成的单例对象始终相同

我正在做下面的代码。这个看起来可以吗?有没有更好的方法来实现我想要实现的目标

  - (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;
    }
B被忽略。 objB中的userAccount是一个

如果用户帐户B在objB中,您将更改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;
}

此设计中存在许多问题:

  • 根据苹果公司的建议,对于singleton,应
    一次分派\u
    ,而不是
    @synchronized(self)

    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;
    
    有关更多详细信息,请参阅此问题:

  • 错误的
    API
    设计将singleton放入
    alloc

    正如alloc方法的名称所示,这意味着将分配一些内存。然而,在你的情况下,情况并非如此。这种覆盖
    alloc
    的尝试会使团队中的其他程序员感到困惑

  • -init
    中使用
    NSAssert
    是个坏主意

    如果要禁用某个方法,请将其放入头文件中禁用:

    - (id)init __attribute__((unavailable)); 
    
    在这种情况下,您将得到一个编译错误,而不是在运行时使应用程序崩溃。 有关更多详细信息,请参阅本文:

    此外,您甚至可以添加不可用的消息:

    - (id)init __attribute__((unavailable("You cannot init this class directly. It needs UserAccountDataSource as a parameter")));
    
  • 有时输入参数会被忽略而没有任何警告

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

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

  • 简言之,不要认为使用参数创建singleton是个好主意。使用传统的单例设计要干净得多

    这可能是为什么单身是个坏主意的另一个迹象。在这种情况下,您可能会更好地使用依赖项注入,但即使我使用依赖项注入,我如何传入userAccount对象?当您实例化
    MyClass
    时,您将调用
    initWithAccount
    ,然后将此对象传递给需要您的
    MyClass
    实例的所有其他类,我很抱歉也许我不明白这是对的。下面的函数-(id)sharedInstanceWithAccount:(UserAccount*)UserAccount{if(!sharedInstance){@synchronized(self){sharedInstance=[[self class]alloc]initWithAccount:UserAccount];}}}返回sharedInstance;}带参数的单例的问题是,可能会有两个不同的调用
    sharedInstanceWithAccount
    来传递不同的帐户(我知道你说不会,但这仍然是可能的)。您可以根据答案使用一个工厂模式,并使用字典,或者忘记单例,实例化单类实例并使用依赖项注入将其传递给每个需要它的类。那么,我如何实现我正在尝试的呢?我只想在应用程序中存在该类的一个副本,这取决于UserAccount。是的,如果使用singleton,您将只有该类的一个副本。如果你想让它依赖于UserAccount,只需在获得singleton后修改该值即可。我的意思是,在构造类时,如何将UserAccount对象传递给类而不引入参数?我可以将其设置为属性,稍后再进行设置,但如果有人忘记设置属性,则会再次出现问题。好的,您可以看看我对该问题的编辑吗?也许这就是你要找的。
    - (id)sharedInstanceWithAccount:(UserAccount *)userAccount {
        if (!sharedInstance) {
            @synchronized(self) {
               sharedInstance = [[[self class] alloc] initWithAccount:userAccount];
            }
        }
        return sharedInstance;
    }