替代app delegate中的全局变量

时间:2011-10-03 12:32:26

标签: iphone ios

我正在开发一个带速度计的应用程序,如动画(仪表和箭头表示仪表上的某些东西)。我将箭头的位置存储在我的app delegate中声明的全局变量中。我这样做是因为箭头位置被更新并被几个类使用。

然而,我不确定这是一个好的或坏的设计决定。我的想法是,因为它是一个非关键的信息(只是一个浮动),所以在全局存储时不会造成任何伤害。但每当我对自己说“全球”这个词时,我的OOP心就会受伤。

或者我有单身人士,但据我所知,当开发人员希望创建一个且只有一个特定对象的实例时,会使用单身人士。

我做得对吗还是有更合适的方式做我做的事情?

3 个答案:

答案 0 :(得分:2)

  

我这样做是因为箭头位置被更新并被几个类使用。

在很多情况下,您可以缩小范围。这减少了组件间依赖性。

  

然而,我不确定这是一个好的或坏的设计决定。我的想法是,因为它是一个非关键的信息(只是一个浮动),所以在全局存储时不会造成任何伤害。但每当我对自己说“全球”这个词时,我的OOP心就会受伤。

也许您可以将状态(浮动值)移动到车速表中的ivar?例如:您可能只显示一个车速表视图:将它添加到视图模型中更有意义吗?或者也许是它的控制器? (是的,在没有源的情况下提供更具体的例子有点困难)

  

或者我有单身人士,但据我所知,当开发人员希望创建一个且只有一个特定对象的实例时,会使用单身人士。

没有必要,并且要保持严重的疼痛。我见过的大多数可可单身人士都不应该被认为是单身人士,并且引起了很多麻烦。更好的是,你可以编写使用零单例的程序。这是理想的,易于测试。因此,依赖于app控制器的程序/类型已经受到可测试性和可重用性的影响。

  

我做得对吗还是有更合适的方式做我做的事情?

在绝大多数情况下,您可以简单地缩小范围并对其进行本地化,同时删除全局状态。通过更多的努力,您可以将该值作为全局删除 - 这是最好的。

虽然这不是一件好事......让我们假设你真的非常真的必须引入全球状态:

  • 使用单身人士。当你想重用它时,你会重写它很有可能。糖包衣什么是丑陋的。如果你的应用程序控制器由于太多的全局状态而变得一团糟,至少你有太多全局状态的事实将是显而易见的。
  • 在您的app控制器中保持您的全局状态。您的app控制器负责其初始化,生命周期和访问。
  • 将该状态提供给依赖项,因此它们不会引用(甚至知道)全局域(app控制器)。然后你可以减少影响。

全局状态和应用程序/执行状态之间也存在明显差异。全球国家应该被淘汰。执行状态不是全局状态,而是本地化执行上下文。执行状态可以在适当的级别重新引入,更改,更新,测试和可预测的重用。一个好的设计将在需要时引入执行状态,并在适当的级别同时避免全局状态。

<强>更新

根据OP中的描述,您的样本与我想象的非常接近。它提供了一些额外的细节。所以下面的示例(你需要在显而易见的领域中添加一些内容以将它们拼凑在一起)演示了如何更新控制器接口,并且最后有两个免费的“其他”方法,它们进一步说明了如何使用它们: / p>

@interface MONArrowPosition : NSObject
{
    float arrowPosition;
}

@end

@implementation MONArrowPosition

- (id)initWithPosition:(float)position
{
    self = [super init];
    if (nil != self) {
        arrowPosition = position;
    }
    return self;
}

@end

@interface MyViewController1 : UIViewController
{
    MONArrowPosition * arrowPosition; // << may actually be held by the model
}

@end

@implementation MyViewController1

- (void)applyRotation
{
    [self rotateLayer:arrow from:self.arrowPosition to:callStatus speed:METER_SPEED];
}

@end

@interface MyViewController2 : UIViewController
{
    MONArrowPosition * arrowPosition; // << may actually be held by the model
}

@end

@implementation MyViewController2

- (void)viewDidLoad
{
    [super viewDidLoad];
    /* ... */
    [self.slider addTarget:self action:@selector(sliderValueDidChange) forControlEvents:controlEvents];
}

- (void)sliderValueDidChange
{
    self.arrowPosition.arrowPosition = self.slider.value;
    [self arrowPositionDidChange];
}

@end

/* elsewhere: */
- (void)initializeArrowPosition
{
    /* The variable is set to a default of 0.0f */
    MONArrowPosition * arrowPosition = [[MONArrowPosition alloc] initWithPosition:0.0f];
    /* ... */
}

- (IBAction)someActionWhichPushesMyViewController1
{
    // depending on the flow of your app, the body of initializeArrowPosition
    // *could* be right here
    MyViewController1 * viewController = [[MyViewController1 alloc] initWithNibName:nibName bundle:bundle];
    viewController.arrowPosition = self.arrowPosition;
    /* push it */
}

然后如果MyViewController1推送MyViewController2,定位和设置箭头位置将很容易。视图控制器也可以在模型中共享一些信息。在您的示例中使用全局,您正在跨越许多实现,这会增加耦合,增加依赖性等。因此,如果您可以采用此方法并本地化执行状态,那么您将有一个良好的开端。那么你可以使用任意数量的MONArrowPositions的任意数量的视图控制器,它们将不受全局状态的影响。再次,我不能使用提供的样本过于具体,但我认为这应该说明我最初概述的概念(我不认为需要进行项目范围的审查)。

答案 1 :(得分:0)

这是让很多程序员在晚上工作的东西。

我尽量不要滥用app委托,我会创建一个单例来存储或多或少的全局信息。除了单身人士或应用代表之外,没有其他方法可以做到这一点。

但是如果只有一个viewController需要信息,那么信息永远不会离开那个viewController。该viewcontroller可以将该信息传递给其他viewcontroller。

在你的情况下,可能有一种想法是拥有一些包含浮点数的directionManager,甚至可以保存CLLocationManager。

答案 2 :(得分:0)

对于这类事情,我喜欢使用NSNotifications。您让所有关心箭头位置的视图控制器都会监听特定通知,并且他们都可以立即更新UI。