【问题标题】:Where to put local variables在哪里放置局部变量
【发布时间】:2009-07-05 04:21:54
【问题描述】:

我有一个视图,视图控制器中的加速度计更新调用了谁的方法。我需要不止一种方法来使用和更改某些变量,例如,一种方法初始化变量,另一种方法在每次加速更新时更新它们的值。

我知道如果它们只用于一种方法,我可以在该方法中声明它们并且没问题。但是由于它们用于多种方法,我一直在实现文件的顶部声明它们,但不是静态的,我知道这是错误的。在 Apple 的一些示例代码中,他们总是在接口文件中声明这些。最好的方法是什么?为什么?

我目前的方法:

@实现

int foo;

备选方案 1:

@实现

静态 int foo;

备选方案 2:

@接口 {

int foo;

谢谢,

【问题讨论】:

    标签: iphone objective-c cocoa cocoa-touch


    【解决方案1】:

    如果变量仅用于单个方法的单次运行,则在方法中声明它们。每次输入方法时都需要初始化它们。这是线程安全的。

    如果变量只需要在单个方法中,但您希望它们在调用之间保持其值,请在方法中将它们声明为静态。它们被初始化为 nil/0/false,或者你可以在声明中初始化它们。这不是线程安全的。

    如果变量需要被单个实现文件中的任何方法或函数访问,而整个程序只需要一个,则在 .m 文件中将它们声明为静态变量。将它们声明为静态会阻止它们被链接器导出并与其他同名的全局变量发生冲突。它们默认初始化为 nil/0/false,或者你可以在声明中初始化它们。这不是线程安全的。

    如果变量需要被对象中的任何方法访问,并且每个实例都需要自己的值,那么你需要一个ivar,在{}之间的接口中声明它。它们被初始化为 nil/0/false。您不能在声明时将它们初始化为任何其他值。您可以在对象的 init 中初始化它们。如果仅从单个线程访问对象,则这是线程安全的。

    【讨论】:

    • 感谢您提供的详细信息。与我在阅读的示例代码中看到的 ivar 声明相比,这很有意义。
    • 我之前所做的是我需要通过单个文件中的任何方法访问的变量,我只需要一个实例。但是,我没有将它们声明为静态的。一切似乎都正常,但这会导致什么问题?
    • 不同之处在于默认情况下该变量将被导出(到链接器),因此它会与其他实现文件中的同名全局变量发生冲突。通过使用“静态”,您可以告诉编译器它仅在此实现文件中是本地的。
    【解决方案2】:

    Objective-C 中的类与 C++ 中的类相似:类分为两个文件。带有@interface 块的头文件定义了类和所有类变量中可用的方法。带有@implementation 的另一个文件提供了这些方法的实现。这是一种遗留问题 - 在“过去”中,编译器可以使用头文件进行优化。更现代的语言(如 Java)不会以这种方式破坏类,因此一开始可能会令人困惑。

    要声明类的成员变量,您应该将它们添加到.h 文件中定义的@interface。这是一个示例 .h 文件,它显示了一个使用一些实例变量定义的类:

    #import <Foundation/Foundation.h>
    #import "PaintViewAnimation.h"
    #import "Transforms.h"
    
    @interface PaintViewZoomAnimator : NSObject {
    
        int                     valueIndex;
        Transforms              target;
        AbstractPaintView *     view;
    }
    
    - (id)initWithView:(AbstractPaintView*)v targetTransforms:(Transforms)t;
    
    - (void)start;
    - (BOOL)step;
    - (void)finish;
    
    @end
    

    这是在 Objective-C 中声明类成员变量的唯一方法。 PaintViewZoomAnimator 的每个实例都将具有可供其所有方法访问的三个变量:valueIndex、target 和 view。你也许可以在别处说“int foo”,因为 Objective-C 实际上只是 C 之上的一个薄层——但那些其他方法是不正确的。

    您可以按照您的建议声明静态变量,但这会显着改变变量的范围。如果我在头文件中声明一个静态变量,则该变量在任何地方都可以访问(假设您包含或导入包含定义的头文件),并且它只有一个副本。如果我有两个 PaintViewZoomAnimator,它们将共享相同的静态变量值。这不是一个很好的面向对象的做法,所以你应该尽量避免它。

    希望对您有所帮助!如果你想开始使用 Objective-C,我会推荐 Aaron Hillegass 的 Cocoa 书——它对这类事情很有帮助。

    【讨论】:

    • “如果我在头文件中声明一个静态变量,则该变量在任何地方都可以访问(假设您包含或导入包含定义的头文件),并且它只有一个副本。”不完全是。每个导入头文件的实现文件中都有一个变量副本;这使得整个应用程序有多个副本。该类将只查看其中一个(与其实现文件对应的那个);其余的都是假货。