How to move non static variables from interface to implementation in objectiveC?
-
16-09-2019 - |
Question
I am trying to write a cocoa touch static library. To keep it simple I would prefer not to use private variables within my interface file. The code right now looks like this:
interface file (myView.h):
@interface myView: UIView {
NSTimer * myTimer;
}
@end
implementation file (myView.h)
@implementation myView
@end
This NSTimer pointer is just a private variable so I tried this: (not working)
interface file (myView.h):
@interface myView: UIView {
}
@end
implementation file (myView.h)
NSTimer * myTimer;
@implementation myView
@end
It seems to work however it turned out that the timer is now a static variable.
Am I doing sth wrong or is there no solution?
Solution
You can't define instance variables in your implementation file.
A possible solution is to have a private structure containing the private variables and have one publicly declared private variable pointing to this private structure:
@interface MyView {
void *privateData;
}
Implementation file:
typedef struct {
NSTimer *myTimer;
} PrivateData;
@implementation MyView()
@property (readonly) PrivateData *privateData;
@end
@implementation MyView
- (id) init {
if (self = [super init]) {
privateData = malloc(sizeof(PrivateData));
self.privateData->myTimer = nil; // or something else
}
return self;
}
-(PrivateData *) privateData {
return (PrivateData *) self->privateData;
}
- (void) myMethod {
NSTimer *timer = self.privateData->myTimer;
}
- (void) dealloc {
// release stuff inside PrivateData
free(privateData);
[super dealloc];
}
@end
It's not beautiful, but it works. Maybe there are better solutions.
OTHER TIPS
Just a note; trying to hide iVar's for the sake of security is silly. Don't bother.
For simplicity's sake, though, it has value.
However, a couple of solutions:
(1) If targeting iPhone OS or 64 bit Cocoa, you can @synthesize the ivar:
Foo.h:
@interface Foo:NSObject
@property(readwrite, copy) NSString *publiclyReadwriteNoiVar;
@property(readonly, copy) NSString *publiclyReadonlyPrivatelyReadwriteNoiVar;
@end
Foo.m:
@interface Foo()
@property(readwrite, copy) NSString *privateProperty;
@end
@implementation Foo
@synthesize publiclyReadwriteNoiVar, publiclyReadonlyPrivatelyReadwriteNoiVar, privateProperty;
@end
(2) Use a private subclass kinda like class clusters:
Foo.h:
@interface Foo:NSObject
@end
Foo.m:
@interface RealFoo:Foo
{
.... ivars here ....
}
@end
@implementation RealFoo
@end
@implementation Foo
+ (Foo *) convenienceMethodThatCreatesFoo
{
.... realFoo = [[RealFoo alloc] init]; ....
return realFoo;
}
@end
Depending on the goal of your encapsulation, there's also the @private directive: