Issue understanding "Referring to Instance Variables" from Apple guide - objective-c

I am trying to understand Referring to Instance Variables from Apple guide but having issue understudying this, Apple Doc says
...When the instance variable belongs to an object that’s not the receiver, the object’s type must be made explicit to the compiler through static typing. In referring to the instance variable of a statically typed object, the structure pointer operator (->) is used.
Suppose, for example, that the Sibling class declares a statically typed object, twin, as an instance variable:
#interface Sibling : NSObject
{
Sibling *twin;
int gender;
struct features *appearance;
}
As long as the instance variables of the statically typed object are within the scope of the class (as they are here because twin is typed to the same class), a Sibling method can set them directly:
- makeIdenticalTwin
{
if ( !twin )
{
twin = [[Sibling alloc] init];
twin->gender = gender;
twin->appearance = appearance;
}
return twin;
}

Referring to instance variable means, accessing the class instance vars
For example:
#interface ClassA : NSObject
{
int value;
}
- (void) setValue:(int) val;
#implementation ClassA
- (void) setValue:(int) val
{
//here you could access class a value variable like this
value = val;
}
Now accessing other classes variables
take for example this class
#interface ClassB : ClassA
{
ClassA aClass;
}
- (void) setValueInAClass:(int) val;
#implementation ClassB
- (void) setValueInAClass:(int) val
{
//class b could access variables from class a like this
aClass->value = val;
}
Please note that this is very un recommended to do, using the "->" breaks the encapsulation of class a, so dont in 99% of the cases referring to class variables using the "->" is a mistake

Related

What is the difference between declaring a member in the extended interface versus in the implementation?

I am seeing two very different behaviors for something that I thought were the exact same.
Defining my private member in the class extension like this:
#interface ClassA ()
#property ClassB* b;
#end
#implementation ClassA
-(ClassA*)initWithClassB:(ClassB*)newB
{
self.b = newB;
return self;
}
-(ClassB*)getB
{
return self.b;
}
Or defining my private member in the class implementation like this:
#interface ClassA ()
#end
#implementation ClassA
ClassB* b;
-(ClassA*)initWithClassB:(ClassB*)newB
{
b = newB;
return self;
}
-(ClassB*)getB
{
return b;
}
The way I am using this code is to create a ClassB object, initialize a ClassA object with that ClassB object, and then add the ClassA object to a mutable array
-(void)init
{
self.classAList = [[NSMutableArray alloc] init];
[self.classAList addObject:[[ClassA alloc] initWithClassB:[self createClassB1]]];
[self.classAList addObject:[[ClassA alloc] initWithClassB:[self createClassB2]]];
[self.classAList addObject:[[ClassA alloc] initWithClassB:[self createClassB3]]];
}
-(ClassB)createClassB1
{
ClassB* classB = new ClassB();
//do some init
return classB;
}
// Same thing fore createClassB2 and createClassB3 except with different data
When I use the first approach, and define my member in the interface extension, I see that each element in my mutable array is indeed what I would expect.
However, using the second approach, I see that my ClassB* b pointer in the ClassA object always ends up pointing to the most recently created ClassB object. That is, once the -(void)init method finishes, the ClassB pointers in each of the ClassA objects points to the ClassB object I created in createClassB3
What is happening here?
I should also mention that the ClassB object is a C++ object and this is a an objective-c++ class.
In your second snippet, b is just a global variable at file scope. The fact that it's inside of the #implementation ... #end is irrelevant. It is not an instance variable nor a property.
With the second approach you're creating a global variable, meaning it's not related to any instance of ClassA, so you will always have one and the same instance of *b pointing to the same object in memory. So anytime you change the value of the *b you're changing the object in memory at which the b variable is pointing, but never creating a new one; to understand it better you're basically initialising every ClassA object with the same ClassB variable (which is *b), so if you change the value at the portion of memory to which *b is pointing you're changing it for all the instances of ClassA created.
Hope it's clear enough.

Static attribute, Static Class, Singleton Pattern

I have 3 class.
Class A contains :
A static variable "dataX".
A setter method to set the data.
A getter method to return the data value.
Class B
Class C.
the flow is as follows:
The Class B instanciates the Class A and initialize the variable "dataX" with the setter method.
Afterwards, the class C instantiates the Class A in the viewDidLoad method and gets the value of the static variable.
But even if the variable in Class A is static, the variable is always null.
I guess that I need to put the Singleton Pattern with a static Class A and not simply a static attribute.
What is the syntax to specify a Class as Static?
The code below:
// HandleMessage.h
#interface HandleMessage : NSObject
#property *NSString nameFile;
// Getter
- (NSString *)getNameFile;
// Setter
- (void)setNameFile: (NSString *) value;
#end
And:
// HandleMessage.m
#import "HandleMessage.h"
#implementation HandleMessage
static nameFile;
#synthesize nameFile ;
// Getter definition
- (NSString *)getNameFile{
return nameFile;
}
// Setter definition
- (void)setNameFile: (NSString *) value{
nameFile = value;
}
When you instantiate another instance of a class of course this instance's value is null.
You can work with singletons or store your data elsewhere (if you want to keep data between app starts in your user defaults using NSUserdefaults)
what do you mean by "Class as Static"??
you can use singleton pattern, which i described in this answer
or using class method
ClassA.h
#interface ClassA
+ (void)setData:(int)data;
+ (int)getData;
#end
ClassA.m
static int sData;
#implementation ClassA
+ (void)setData:(int)data {
sData = data;
}
+ (int)getData {
return data;
}
#end

storing instance reference in singleton in obj-c

Let's say I have 2 classes, A and B. A is a singleton. I declare A in B, so I can access the singletons vars in methods in B.
B then creates an instance of another class, say class C.
C Then creates an instance of another class, say class D.
What I need to do is run a method in the instance of class B, from class D, and that's what is driving me nuts.
My first thought was to put a reference to the instance of class b, in my singleton (class A), something like...
sharedInstance.classBReference = self;
..and then declare the singleton in Class D, and then use something like this in class D instance...
[sharedInstance.classBInstance classBInstanceMethod];
But of course as soon as I did..
classB *classBReference;
In the header of my singleton, it game me the "unknown type" which I read about on here, so instead, I put a
#class classB;
above the #interface, and then I was able to declare...
classB *classBReference;
Without an error of unknown type, but in the init method of class B, this...
sharedInstance.classBReference = self;
Still gives me an error of type
"property classBReference not found on objet of type "class A*" (the singleton) did you mean to access ivar classBReference?"
And I have no idea why it's doing that, what's the solution? or is there a better way to do what I'm trying to do?
Dots and Arrows
The "dot notation" is a somewhat recent addition to Objective-C and provides a shorthand notation for accessors. If you have a pointer to an object (or a struct!), you cannot access its instance variables with . but only with ->.
Your line
sharedInstance.classBReference = self;
is exactly the same as
[sharedInstance setClassBReference:self];
The problem is that you don't have any such method -setClassBReference:. In order to set the instance variable, you must instead write
sharedInstance->classBReference = self;
#protected variables
After switching your line with this one, you may (if you haven't made it #public) see the error
Instance variable 'classBReference' is private
In this case, you need to alter your classA interface so that classBReference is declared to be #public. Your list of instance variables in classA should look something like
#interface classA : NSObject
{
//#protected
//(The #protected keyword is optional when at the beginning of the list; instance
//variables are protected by default, which is why you're needing to declare your
//instance variable classBReference to be #public (since classB is not a subclass
//of classA and consequently cannot access its protected instance variables).
//....
//some protected instance variables
//....
#private
//....
//some private instance variables
//....
#public
//....
//some public instance variables
classB *classBReference;
//....
#protected
//....
//some more protected instance variables
//Note that #protected is not optional in order to make the instance variables
//here be protected since they are declared subsequent to the prior #public.
//....
}
//....
#end
Using #properties
The case of classBReference
That being said, it is widely regarded as a better practice to use accessors rather than instance variables in general. In order to do this, you should add a property to your classA interface:
#interface classA : NSObject
{
classB *classBReference;
}
#property classB *classBReference;
#end
and synthesize the classBReference property to access the classBReference instance variable in classA's implementation as follows:
#implementation classB
#synthesize classBReference = classBReference;
The general set-up
The #synthesize is somewhat unclear on account of the fact that we have both an instance variable and a property with the same name. Some clarification is in order. In general, in a class's ("MyObject" in this example) #interface one declares an instance variable ("myVariable" in this example) and a property ("myProperty" in this example).
#interface MyObject : NSObject
{
SomeObject *myVariable;
}
#property SomeObject *myProperty;
#end
In the class's #implementation one has the line
#synthesize myProperty = myVariable.
The result of this code is that, given an instance
MyObject *object = //...
of the class, one is able to write
SomeObject *someObject = //...
[object setMyProperty:someObject];
and
SomeObject *someOtherObject = [object myProperty];
The result of calling -setMyProperty: on the instance of MyObject is that myVariable is set equal to the argument passed into the method--in this case someObject. Similarly, the result of calling -myProperty on the instance of MyObject is that myVariable is returned.
What does it get us?
Without the #property and #synthesize directives, one would have to declare the methods
- (void)setMyProperty:(SomeObject *)myProperty;
- (SomeObject *)myProperty;
manually and define them manually as well:
- (void)setMyProperty:(SomeObject *)myProperty
{
myVariable = myProperty;
}
- (SomeObject *)myProperty
{
return myVariable;
}
The #property and #synthesize provide some abridgment to this code. The amount of code that is generated for you becomes even more beneficial when you use various of the property attributes.
Note: There is more to say about the #property and #synthesize directives. For a start, not only can you write #synthesize myProperty; omitting the variable name, you can omit the synthesizing of myProperty entirely, and the variable names that are used automatically are different from one another in these two cases.
A Bit More on Dot Notation
The dot notation from your question provides another layer of abbreviation. Rather than having to write
[object setMyProperty:someObject];
you are now able to write
object.myProperty = someObject;
Similarly, rather than having to write
SomeObject *someOtherObject = [object myProperty];
you are now able to write
SomeObject *someOtherObject = object.myProperty;
It is important to note that this is just just notation. Though it "kinda looks like" we're doing simple assignment when we "set object.myProperty equal to someObject", that is not the case. In particular, when we execute the line
object.myProperty = someObject;
the method
- (void)setMyProperty:(SomeObject *)someObject
is executed. For this reason, dot notation is a subject of some contention. It is a convenience, but it is important to keep in mind what your code is doing.
The error message tells you the answer. You should define classBReference as property or use classBReference as ivar.
It sounds like you'd be less confused by avoiding the global variable (aka singleton). Give the C a reference to the B when the B creates the C. Give the D a reference to the B when the C creates the D.
If you need to avoid a retain cycle, make the back-references to the B either weak (if your deployment target is at least iOS 5.0) or unsafe_unretained (if your deployment target is earlier than iOS 5.0).

getter and setter method in objective c?

New to Objective-C, and i am basically from c++ background. I am learning now objective-c and would like to get confirmation of what i understood is write or wrong?. Kindly advise.
I have the following class:
#interface Test: NSObject
{
int instance1;
}
#property int instance1;
- (void) sayHello;
#end
Class 'Test' has a instance variable instance1. If the member function ie: sayHello wants to access the variable, it has to happen through getter/setter functions. So, There are two ways to get it :
User can define.
We can get the help from the compiler?. How?.
declare the same variable as a property, and synthesize it, the the compiler
gets the code of getter/setter for us for that particular variable.
So, Untimately, getter/setter is the only way to access the variable in the method implementation, ie. both self.instance1 = 100; and instance1 = 100 need getter/setter.
Having missed both 1. and 2., there is no way to access the instance1 variable.
Also, instance1 is a pubic variable can can be accessed outside of the class with object instance.
Test *t = [[ Test alloc] init];
t.instance1 = 200;
Questions:
Is there any way to make instance1 is "private", so that I can not access the instance
variable outside the class?
Is there anything wrong in my understanding?
If the member function ie: sayHello wants to access the variable, it has to happen through getter/setter functions.
It doesn't have to. You can access ivars directly, without using accessor methods:
- (void)sayHello {
instance1 = 123;
}
You can define private ivars by declaring them in the implementation file, not the header:
#implementation Test {
int privateVar;
}
// ... additional implementation, methods etc.
#end
Note, that since Xcode 4.4 you don't have to declare your ivars anymore. You simply declare a property. The ivar and the accessor methods will be synthessized automatically.
For more details, I recommend reading my answer to this question: Declaration of variables
ion SomeDelegate.h
#interface SomeDelegate : NSWindowController {
#private
int fLanguage;
int fDBID;
bool fEndEditingIsReturn;
#public
int fIsMyLastMSG;
}
#property int language;
In SomeDelegate.mm
#implementation SomeDelegate
#synthesize language=fLanguage;
In my example you get private and public variables, private variable fLanguage has a property for synthesize accessor methods.

Objective-C Static Class Level variables

I have a class Film, each of which stores a unique ID. In C#, Java etc I can define a static int currentID and each time i set the ID i can increase the currentID and the change occurs at the class level not object level. Can this be done in Objective-C? I've found it very hard to find an answer for this.
Issue Description:
You want your ClassA to have a ClassB class variable.
You are using Objective-C as programming language.
Objective-C does not support class variables as C++ does.
One Alternative:
Simulate a class variable behavior using Objective-C features
Declare/Define an static variable within the classA.m so it will be only accessible for the classA methods (and everything you put inside classA.m).
Overwrite the NSObject initialize class method to initialize just once the static variable with an instance of ClassB.
You will be wondering, why should I overwrite the NSObject initialize method. Apple documentation about this method has the answer: "The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.)".
Feel free to use the static variable within any ClassA class/instance method.
Code sample:
file: classA.m
static ClassB *classVariableName = nil;
#implementation ClassA
...
+(void) initialize
{
if (! classVariableName)
classVariableName = [[ClassB alloc] init];
}
+(void) classMethodName
{
[classVariableName doSomething];
}
-(void) instanceMethodName
{
[classVariableName doSomething];
}
...
#end
References:
Class variables explained comparing Objective-C and C++ approaches
As of Xcode 8, you can define class properties in Obj-C. This has been added to interoperate with Swift's static properties.
Objective-C now supports class properties, which interoperate with Swift type properties. They are declared as: #property (class) NSString *someStringProperty;. They are never synthesized. (23891898)
Here is an example
#interface YourClass : NSObject
#property (class, nonatomic, assign) NSInteger currentId;
#end
#implementation YourClass
static NSInteger _currentId = 0;
+ (NSInteger)currentId {
return _currentId;
}
+ (void)setCurrentId:(NSInteger)newValue {
_currentId = newValue;
}
#end
Then you can access it like this:
YourClass.currentId = 1;
val = YourClass.currentId;
Here is a very interesting explanatory post I used as a reference to edit this old answer.
2011 Answer: (don't use this, it's terrible)
If you really really don't want to declare a global variable, there another option, maybe not very orthodox :-), but works... You can declare a "get&set" method like this, with an static variable inside:
+ (NSString*)testHolder:(NSString*)_test {
static NSString *test;
if(_test != nil) {
if(test != nil)
[test release];
test = [_test retain];
}
// if(test == nil)
// test = #"Initialize the var here if you need to";
return test;
}
So, if you need to get the value, just call:
NSString *testVal = [MyClass testHolder:nil]
And then, when you want to set it:
[MyClass testHolder:testVal]
In the case you want to be able to set this pseudo-static-var to nil, you can declare testHolder as this:
+ (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test {
static NSString *test;
if(shouldSet) {
if(test != nil)
[test release];
test = [_test retain];
}
return test;
}
And two handy methods:
+ (NSString*)test {
return [MyClass testHolderSet:NO newValue:nil];
}
+ (void)setTest:(NSString*)_test {
[MyClass testHolderSet:YES newValue:_test];
}
Hope it helps! Good luck.
On your .m file, you can declare a variable as static:
static ClassName *variableName = nil;
Then you can initialize it on your +(void)initialize method.
Please note that this is a plain C static variable and is not static in the sense Java or C# consider it, but will yield similar results.
In your .m file, declare a file global variable:
static int currentID = 1;
then in your init routine, refernce that:
- (id) init
{
self = [super init];
if (self != nil) {
_myID = currentID++; // not thread safe
}
return self;
}
or if it needs to change at some other time (eg in your openConnection method), then increment it there. Remember it is not thread safe as is, you'll need to do syncronization (or better yet, use an atomic add) if there may be any threading issues.
As pgb said, there are no "class variables," only "instance variables." The objective-c way of doing class variables is a static global variable inside the .m file of the class. The "static" ensures that the variable can not be used outside of that file (i.e. it can't be extern).
Here would be an option:
+(int)getId{
static int id;
//Do anything you need to update the ID here
return id;
}
Note that this method will be the only method to access id, so you will have to update it somehow in this code.
(Strictly speaking not an answer to the question, but in my experience likely to be useful when looking for class variables)
A class method can often play many of the roles a class variable would in other languages (e.g. changed configuration during tests):
#interface MyCls: NSObject
+ (NSString*)theNameThing;
- (void)doTheThing;
#end
#implementation
+ (NSString*)theNameThing { return #"Something general"; }
- (void)doTheThing {
[SomeResource changeSomething:[self.class theNameThing]];
}
#end
#interface MySpecialCase: MyCls
#end
#implementation
+ (NSString*)theNameThing { return #"Something specific"; }
#end
Now, an object of class MyCls calls Resource:changeSomething: with the string #"Something general" upon a call to doTheThing:, but an object derived from MySpecialCase with the string #"Something specific".
u can rename the class as classA.mm and add C++ features in it.
Another possibility would be to have a little NSNumber subclass singleton.