Global Variables in Objective C - objective-c

I have a counter which I use to get an object at that counters index and I need to access it in another class.
How are static variables declared in Objective C?

Rather than make it global, give one class access to the other class's counter, or have both classes share a third class that owns the counter:
ClassA.h:
#interface ClassA {
int counter;
}
#property (nonatomic, readonly) int counter;
ClassA.m
#implementation ClassA
#synthesize counter;
ClassB.h:
#import "ClassA.h"
#interface ClassB {
ClassA *a;
}
ClassB.m:
#implementation ClassB
- (void)foo {
int c = a.counter;
}

Hi alJaree,
You declare a static variable in the implementation of Your class and enable access to it through static accessors:
some_class.h:
#interface SomeClass {...}
+ (int)counter;
#end
some_class.m:
#implementation SomeClass
static int counter;
+ (int)counter { return counter; }
#end

Related

Objective-C public get set method for private property

I wonder if it is possible to use #synthesize on a private #property so that the get/set methods have public access.
Right now my code looks something like this
SomeClass.h
#import <Foundation/Foundation.h>
#interface SomeClass : NSObject
{
#private
int somePrivateVariable;
}
#end
SomeClass.m
#import "SomeClass.h"
#interface SomeClass ()
#property int somePrivateVariable;
#end
#implementation
#synthesize somePrivateVariable;
#end
Then in some outside function I want to be able to write:
#import "SomeClass.h"
SomeClass *someClass = [[SomeClass alloc] init];
[someClass setSomePrivateVariable:1337]; // set the var
NSLog("value: %i", [someClass getSomePrivateVariable]); // get the var
I know that I can just create my own get/set methods in the header file but I would enjoy using the #synthesize very much more.
If you want a public property to mirror a private one, just override the public property's getter and setter and return the private one.
#interface Test : NSObject
#property NSObject *publicObject;
#end
Then, in the implementation:
#interface Test ()
#property NSObject *privateObject;
#end
#implementation Test
- (NSObject *)publicObject
{
return self.privateObject;
}
- (void)setPublicObject:(NSObject *)publicObject
{
self.privateObject = publicObject;
}
#end

NSArray as Private data in Class?

I recently started learning Objective-C. I decided to make a class called "Student" with the properties age, name, and importantly, classes. I have put the classes in an NSArray full of NSStrings. My issue is, if I define it as an #property, it automatically creates a setter and getter method for it. I dont want that in my class. How do I define an NSArray as private data in the class, without allowing for the setter and getter?
Here's the header code:
#import <Foundation/Foundation.h>
#interface Student : NSObject
#property NSString * Name;
#property unsigned short age;
#property BOOL isFullTime;
#property NSMutableArray * Classes;
#end
[NSGreeter ThanksGuys];
You have a few popular options. Of course, you can substitute types as you wish:
A:
Place it in the header, and specify #private access.
// Student.h
#interface Student : NSObject
{
#private // << note: protected is the default when declared in this scope.
NSArray * ivar;
}
#end
B:
Place it in the #implementation block. you could specify access, but that is not usually an issue because it is not visible to any other translation.
// Student.m
#implementation Student
{
#private // << note: private is the default when declared in this scope.
NSArray * ivar;
}
#end
C:
Declare it in the class continuation:
// Student.m
#interface Student ()
{
NSArray * ivar;
}
#end
D:
Declare as a property in the class continuation:
// Student.m
#interface Student ()
#property (nonatomic, copy) NSArray * ivar;
#end
#interface Student : NSObject {
#private
NSMutableArray * Classes;
}
#property NSString * Name;
#property unsigned short age;
#property BOOL isFullTime;
#end
Use the keyword #private
#interface Student : NSObject
{
#private
NSMutableArray * Classes;
}
#property NSString * Name;
#property unsigned short age;
#property BOOL isFullTime;
#end

ObjectiveC: where to declare private instance properties?

I have the following class interface:
#interface MyClass : NSObject
#property int publicProperty;
#end
then the implementation:
#interface MyClass() // class extension
- (void)privateMethod; // private methods
#end
#implementation MyClass {
int _privateProperty;
}
#property int privateProperty = _privateProperty;
#end
this is what the Apple guy showed in WWDC, but is there any reason for NOT putting _privateProperty in class extension like:
#interface MyClass() // class extension
{
int _privateProperty;
}
- (void)privateMethod; // private methods
#end
Thanks!
I usually "force" private with an extension in the implementation
In your header
#interface MyClass : NSObject
{
}
#property (nonatomic, assign) int publicProperty;
#end
In your implementation file:
#interface MyClass ()
#property (nonatomic, assign) int privateProperty;
#end
#implementation MyClass
#synthesize privateProperty;
#synthesize publicProperty;
#end
You dont have to declare your ivars in both the interface and the implementation.Because you want to make them private you can just declared them in the implementation file like so:
#implementation {
int firstVariable;
int secondVariable;
...
}
//properties and code for your methods
If you wanted to, you can then create getter and setter methods so that you can access those variables.
The person you spoke to was right, though there is not any reason why you would NOT declare them the same way in the interface. Some books actually teach you that the #interface shows the public face of the class and what you have in the implementation will be private.
Do you mean you want to declare private instance variables?
You can do this:
#interface MyClass()
{
#private //makes the following ivar private
int _privateProperty;
}
With the "modern runtime" (64-bit MacOS post-10.5 and all versions of iOS), you don't need to declare instance variables at all.
// MyClass.h
#interface MyClass : NSObject
#property int publicProperty;
#end
// MyClass.m
#implementation MyClass
#synthesize publicProperty = _privateProperty; // int _privateProperty is automatically synthesized for you.
#end

Access private instance variable of parent class

I can't figure out why class B can access class A private instance variable.
Here is my code
A.h
#import <Foundation/Foundation.h>
#interface A : NSObject
{
#private
int x;
}
#property int x;
-(void)printX;
#end
A.m
#import "A.h"
#implementation A
#synthesize x;
-(void)printX
{
NSLog(#"%i", x);
}
#end
B.h
#import "A.h"
#interface B : A
{
}
#end
main.m
B *tr = [[B alloc] init];
tr.x = 10;
[tr printX];
Here I can access instance variable of A class x despite it is declarated as private ?
You are not accessing the private variable there, at least not directly: you are accessing a public property, which has legitimate access to the private ivar.
Your code is equivalent to this:
B *tr = [[B alloc] init];
[tr setX:10];
[tr printX];
The #synthesize statement created the getter and the setter methods for you. If you want only a getter to be available, mark your property readonly, and do all writings through an ivar in the A class.
In your implementation file do this on the top..
#interface A : NSObject
{
#private
int x;
}
#property int x;
#end
this way x will be private since it is in the implementation file. not the interface section...all classes import the interface section of A ..so it's variable are accessible to its subclasses.

Hide instance variable from header file in Objective C

I came across a library written in Objective C (I only have the header file and the .a binary).
In the header file, it is like this:
#interface MyClass : MySuperClass
{
//nothing here
}
#property (nonatomic, retain) MyObject anObject;
- (void)someMethod;
How can I achieve the same thing? If I try to declare a property without its corresponding ivar inside the interface's {}, the compiler will give me an error. Ultimately, I want to hide the internal structure of my class inside the .a, and just expose the necessary methods to the header file. How do I declare instance variables inside the .m? Categories don't allow me to add ivar, just methods.
For 64 bit applications and iPhone applications (though not in the simulator), property synthesis is also capable of synthesizing the storage for an instance variable.
I.e. this works:
#interface MyClass : MySuperClass
{
//nothing here
}
#property (nonatomic, retain) MyObject *anObject;
#end
#implementation MyClass
#synthesize anObject;
#end
If you compile for 32 bit Mac OS X or the iPhone Simulator, the compiler will give an error.
You may use of the same idiom used in Cocoa classes. If you have a look to NSString class interface in NSString.h you'll see that there is no instance variable declared. Going deeper in GNUstep source code you'll find the trick.
Consider the following code.
MyClass.h
#interface MyClass : NSObject
// Your methods here
- (void) doSomething;
#end
MyClass.m
#interface MyClassImpl : MyClass {
// Your private and hidden instance variables here
}
#end
#implementation MyClass
+ (id) allocWithZone:(NSZone *)zone
{
return NSAllocateObject([MyClassImpl class], 0, zone);
}
// Your methods here
- (void) doSomething {
// This method is considered as pure virtual and cannot be invoked
[self doesNotRecognizeSelector: _cmd];
}
#end
#implementation MyClassImpl
// Your methods here
- (void) doSomething {
// A real implementation of doSomething
}
#end
As you can see, the trick consist in overloading allocWithZone: in your class. This code is invoked by default alloc provided by NSObject, so you don't have to worry about which allocating method should be used (both are valid). In such allocWithZone:, you may use the Foundation function NSAllocateObject() to allocate memory and initialize isa for a MyClassImpl object instead of MyClass. After that, the user is dealing with a MyClassImpl object transparently.
Of course, the real implementation of your class shall be provided by MyClassImpl. The methods for MyClass shall be implemented in a way that considers a message receiving as an error.
You can use a class extension. A class extension is similar as category but without any name. On the Apple documentation they just define private methods but in fact you can also declare your internal variables.
MyClass.h
#class PublicClass;
// Public interface
#interface MyClass : NSObject
#property (nonatomic, retain) PublicClass *publicVar;
#property (nonatomic, retain) PublicClass *publicVarDiffInternal;
- (void)publicMethod;
#end
MyClass.m
#import "PublicClass.h"
#import "InternalClass.h"
// Private interface
#interface MyClass ( /* class extension */ )
{
#private
// Internal variable only used internally
NSInteger defaultSize;
// Internal variable only used internally as private property
InternalClass *internalVar;
#private
// Internal variable exposed as public property
PublicClass *publicVar;
// Internal variable exposed as public property with an other name
PublicClass *myFooVar;
}
#property (nonatomic, retain) InternalClass *internalVar;
- (void)privateMethod;
#end
// Full implementation of MyClass
#implementation MyClass
#synthesize internalVar;
#synthesize publicVar;
#synthesize publicVarDiffInternal = myFooVar
- (void)privateMethod
{
}
- (void)publicMethod
{
}
- (id)init
{
if ((self = [super init]))
{
defaultSize = 512;
self.internalVar = nil;
self.publicVar = nil;
self.publicVarDiffInternal = nil; // initialize myFooVar
}
return self;
}
#end
You can give MyClass.h to anyone with just your public API and public properties. On MyClass.m you declare your member variable private and public, and your private methods, on your class extension.
Like this it's easy to expose public interfaces and hide detail implementation. I used on my project without any troubles.
According to the documentation I've been looking at there is no problem. All you have to do to hide instance variables is to declare them at the start of the #implementation section, inside { ... }. However, I'm a relative newcomer to Objective C and there's a chance I have misunderstood something - I suspect that the language has changed. I have actually tried this system, using XCode 4.2, building code for the iPad, and it seems to work fine.
One of my sources for this idea is the Apple developer documentation at http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocDefiningClasses.html, which gives this pattern:
#implementation ClassName
{
// Instance variable declarations.
}
// Method definitions.
#end
Two possibilities:
It could be taking advantage of the modern runtime's ability to synthesize instance variables, as bbum suggested.
The property might not have an underlying instance variable in that class. Properties do not necessarily have a one-to-one mapping with instance variables.
No you can't. But you can do this if you're not using #property:
.h
#interface X : Y {
struct X_Impl* impl;
}
-(int)getValue;
#end
.m
struct X_Impl {
int value;
};
...
#implementation X
-(void)getValue {
return impl->value * impl->value;
}
#end
How about a macro trick?
Have tested code below
have tested with dylibs - worked fine
have tested subclassing - Warning! will break, I agree this makes the trick not that useful, but still I think it tells some about how ObjC works...
MyClass.h
#interface MyClass : NSObject {
#ifdef MYCLASS_CONTENT
MYCLASS_CONTENT // Nothing revealed here
#endif
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, assign) int extra;
- (id)initWithString:(NSString*)str;
#end
MyClass.m
// Define the required Class content here before the #import "MyClass.h"
#define MYCLASS_CONTENT \
NSString *_name; \
int _extra; \
int _hiddenThing;
#import "MyClass.h"
#implementation MyClass
#synthesize name=_name;
#synthesize extra=_extra;
- (id)initWithString:(NSString*)str
{
self = [super init];
if (self) {
self.name = str;
self.extra = 17;
_hiddenThing = 19;
}
return self;
}
- (void)dealloc
{
[_name release];
[super dealloc];
}
#end
DON'T do this, but I feel it should be noted that the runtime has the ability to add ivars whenever you want with class_addIvar
I was able to do the following in my library:
myLib.h:
#interface MyClass : SomeSuperClass <SomeProtocol> {
// Nothing in here
}
- (void)someMethods;
#end
myLib.m
#interface MyClass ()
SomeClass *someVars;
#property (nonatomic, retain) SomeClass *someVars;
#end
#implementation MyClass
#synthesize someVar;
- (void)someMethods {
}
#end
The protocol is optional of course. I believe this also makes all your instance variables private though I'm not 100% certain. For me it's just an interface to my static library so it doesn't really matter.
Anyway, I hope this helps you out. To anyone else reading this, do let me know if this is bad in general or has any unforeseen consequences. I'm pretty new to Obj-C myself so I could always use the advice of the experienced.
I don't think the following code written in another answer is working as expected.
The "SomeClass *someVars" defined in the extension class is not an instance variable of MyClass. I think it is a C global variable. If you synthesize someVars, you will get compile error. And self.someVars won't work either.
myLib.h
#interface MyClass : SomeSuperClass <SomeProtocol> {
// Nothing in here
}
- (void)someMethods;
#end
myLib.m
#interface MyClass ()
SomeClass *someVars;
#property (nonatomic, retain) SomeClass *someVars;
#end
#implementation MyClass
#synthesize someVar;
- (void)someMethods {
}
#end