【问题标题】:Static variable in singleton [closed]单例中的静态变量[关闭]
【发布时间】:2012-06-21 18:49:06
【问题描述】:

我有一个单例,想创建一个内部标志变量,该变量应该表明单例已“释放”,当我得到单例实例时,它应该重新初始化。

对于这种情况,我决定使用静态变量

static BOOL wasReleased = NO; 

并在销毁函数中将其设置为“YES”:

- (void)destroy
{
    wasReleased = YES;
    ...release internal singleton resources...
}

但是当我尝试获取单例实例时,此变量值始终为“NO”,因此内部资源在释放后从未重新初始化:

+ (MySingleton *)sharedInstance
{
    if (sharedCoordinator == nil)
    {
        sharedCoordinator = [[super alloc] init];
        [sharedCoordinator initialize];
    }

    if (wasReleased) 
    {
        [sharedCoordinator initialize];
    }

    return sharedCoordinator;
}

我对这种情况的理解可能有误,请为我澄清一下。

【问题讨论】:

  • 你的意思是NO 你发送destroy?
  • 你手动调用destroy吗?因为我想否则该对象将永远不会被销毁
  • Josh Caswell,是的,发送destroy 后,它的值为NO。我仅在上述两种情况下更改“wasReleased”的值。我在destroy 中检查wasReleased 的值,所以这是我所期望的YES,但之后不是。 Joerg Simon,是的,我正在手动调用“销毁”,我正在使用断点来确保。

标签: objective-c ios variables static singleton


【解决方案1】:

删除你的静态 wasReleased 实例变量并使其成为 MySingleton 类的属性(不要忘记合成它)

@property (nonatomic, assign) BOOL wasReleased;

然后在-destroy 方法中:

- (void)destroy
{
    self.wasReleased = YES;
    //...release internal singleton resources...
}

然后(删除你的静态 ivar sharedCoordinator - 我想你有一个)

+ (MySingleton *)sharedInstance
{
    static MySingleton *sharedCoordinator = nil;
    if (!sharedCoordinator)
    {
        sharedCoordinator = [[MySingleton alloc] init];
        [sharedCoordinator initialize];
    }

    if (sharedCoordinator.wasReleased) 
    {
        [sharedCoordinator initialize];
        sharedCoordinator.wasReleased = NO; //If you are not doing it in the -initialize method
    }

    return sharedCoordinator;
}

【讨论】:

  • 您能解释一下为什么您认为这会有所帮助吗?
  • 因为,声明一个静态实例变量(对于wasReleasedsharedCoordinator 的两种情况)并在类方法中使用它是没有意义的,因为在类方法中你不在实例的范围。类方法不能访问实例变量,但是你可以从实例中访问它们...
  • 它不是一个实例变量——如果是它就不能这样声明——而且没有“静态实例变量”这样的东西。这是一个static 文件级变量(可在类方法中访问);这是 ObjC 中“类成员变量”的解决方法。
  • 是的,没有 - 你是对的。我没有提供很好的解释...
  • 嗯,你是对的,刚刚测试了他的解决方案,它按预期工作,他可能没有调用destroy方法:)
【解决方案2】:

我对这种情况的理解可能有误,请澄清一下 我。

你为什么首先使用单例?单例永远不需要被释放或重新初始化。如果您需要做这些事情,很可能您应该在需要时简单地创建一个类的新实例。

此外,最好避免使用 -initialize 作为实例方法名称,因为这很容易与每个类都有的类方法 +initialize 混淆。

【讨论】:

    【解决方案3】:

    这并不能解决您的直接担忧,但您应该重新考虑您的设计。销毁单例不是一个好主意。如果您试图释放大量资源(图像、视频等),您可以让单例上的实际方法负责重新实例化它们。

    以下将无法按预期工作:

    - (id)initSomeClassUsingTheSingleton
    {
      mySingletonVariable = [MySingleton sharedInstance];
    }
    
    - (void)someOtherFunctionOccuringAfterDestroy
    {
      [mySingletonVariable aMethodOnTheSingleton];
    }
    

    这是使用单例的一种完全有效的方法,但在你的情况下你不能这样做。相反,你的单例应该有如下方法:

    - (void)aMethodOnTheSingleton
    {
      //if resources for method not allocated
        // .. allocate
    
      // do the rest
    }
    

    【讨论】:

    • 嗨,大卫 V,感谢您的回答。当然,我不想发布单例实例,只是封装在单例中的资源。只有一个问题是我无法理解我的 bool 标志没有保持其值的原因。据我了解,您的resourcesForMethodNotAllocated 与我的wasReleased 含义相同。
    • 我编辑了帖子以澄清 if(resourcesForMethodNotAllocated) 只是概念性的。它可能与 wasReleased 布尔值相同,但我建议将其设为实例变量。如果不同的方法需要不同的资源,它也可能不同。我不知道你的问题是什么。
    猜你喜欢
    • 2021-11-29
    • 2018-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多