views:

220

answers:

2

I have a view who's methods are called by the accelerometer updates in the view controller. I need more than one method to use and change certain variables, for example one method initializes the variable and another updates their value with each accel update.

I know if they were only used on one method I could declare them inside that method and be fine. But since they are used in multiple methods I have been declaring them at the top of the implementation file, but not as static which I know believe is wrong. In some of Apple's sample code they always declare these in the interface file. What is the best way to do this and why?

My current method:

@implementation

int foo;

Alternative 1:

@implementation

static int foo;

Alternative 2:

@interface {

int foo;

Thanks,

A: 

Hi Aaron,

Classes in Objective-C are similar to classes in C++: the class is broken into two files. A header file with a @interface block defines the methods available in the class and all class variables. The other file with the @implementation provides the implementation of those methods. This is sort of a legacy thing - in the "old days" the compiler could be optimized using the header files. More modern languages like Java don't break classes this way, so it can be confusing at first.

To declare member variables of a class, you should add them to the @interface defined in the .h file. Here's an example .h file that shows a class being defined with a few instance variables:

#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

This is the only way to declare member variables of a class in Objective-C. Each instance of PaintViewZoomAnimator will have three variables accessible to all of it's methods: valueIndex, target, and view. You may be able to say "int foo" elsewhere since Objective-C is really just a thin layer on top of C - but those other approaches are incorrect.

You can declare static variables as you've suggested, but that significantly changes the scope of the variable. If I declare a static variable in a the header file, the variable is accessible everywhere (providing you include or import the header file containing the definition), and there is only one copy of it. If I had two PaintViewZoomAnimators, they would share the same values for static variables. This isn't really a good object-oriented practice, so you should try to avoid it.

Hope that helps! If you're looking to get started with Objective-C, I'd recommend the Cocoa book by Aaron Hillegass - it can really help with things like this.

Ben Gotow
“If I declare a static variable in a the header file, the variable is accessible everywhere (providing you include or import the header file containing the definition), and there is only one copy of it.” Not exactly. There is one copy of the variable in every implementation file that imported the header; this makes for multiple copies across the entire application. The class will only look at one of them (the one corresponding to its implementation file); all the rest are fakes.
Peter Hosey
+4  A: 

If variables are needed only for a single run of a single method, then you declare them inside the method. You need to initialize them each time you enter the method. This is thread safe.

If variables are needed only in a single method, but you want them to keep their value between calls, declare them as static in the method. They are initialized to nil/0/false, or you can initialize them in the declaration. This is not thread safe.

If variables need to be accessed by any method or function in a single implementation file, and you only need one for the entire program, then declare them as static variable in the .m file. Declaring them as static stops them from being exported by the linker and clashing with other identically named global variables. They are initialized to nil/0/false by default, or you can initialize them in the declaration. This is not thread safe.

If variables need to be accessed by any method in an object, and each instance needs its own values, then you need an ivar, declare it in the interface between the { }. They are initialized to nil/0/false. You cannot initialize them to any other value at declartion time. You can initialize them in your object's init. This is thread safe if the object is accessed only from a single thread.

Peter N Lewis
Thank you for the detail. This makes a lot of sense compared to how I have seen ivar declared in sample code I have been reading.
Aaron
What I had done previously is I needed variable accessed by any method in a single file and I only needed one instance. I however did not declare them as static. Everything seemed to work but what problems would this cause?
Aaron
The difference is that the variable will be exported (to the linker) by default, so it will clash with identically named global variables in other implementation files. By using "static" you tell the compiler it is local to this implementation file only.
Peter N Lewis