storing instance reference in singleton in obj-c - objective-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).

Related

Passing a class instance as a parameter to one of its own functions

When a class of properties (let's call it class_X) is being instantiated from another class, all of class_X's methods and functions are also included in every instance.
Q1: Wouldn't that add substantial overheads, especially if there are multiple instances of that class?
The class instance (class_X) could then be passed to other methods and functions in other classes as a parameter.
Q2: Is it safe to pass it as a parameter to a C-style function (let's call it function_C) which resides in the same class (function_C resides in class_X)?
Thanks in advance.
UPDATE: Here's some code to illustrate:
class_X header:
//class_X.h
#interface class_X : NSObject
#property (nonatomic, assign) NSInteger intProp;
#property (nonatomic, strong) NSArray *arrProp;
void function_C (class_X *cx);
#end
class_X implementation:
//class_X.m
#import "class_X.h"
#implementation class_X
void function_C (class_X *cx)
{
//code...
}
#end
instantiating class_X:
#implementation someOtherViewController
- (void) viewDidLoad {
[super viewDidLoad];
class_X *cx = [[class_X alloc] init];
cx.intProp = 123;
cx.arrProp = #[#"one", #"two", #"three"];
function_C (cx); //does this not cause some sort of recursion?
}
#end
To have some naming conventions: "class instances" is akin of ambiguous. There are
instances (or instance objects) having a class.
classes, akin of type for an instance object.
class objects
So I assume that you want to use "instance objects of class X", when you write "class instances".
To your Q:
No, there is no overhead. Objective-C is a class-based programming language in contrast to JS that is prototype-based. That has the consequence that every instance has all instance methods that are declared as instance methods by the class. Therefore they are stored only a single time for all instances. The memory footprint for the methods does not depend on the number of instances are created. It is a one-timer. (The memory footprint for properties depends heavily on the number of instances.)
It is completely safe to pass references to instances to a function. Moreover the function can be defined everywhere. Of course, it has to see the interface of the class f the passed instance, probably via an import.

Simple Class Extension / Inheritance Clarification

I've been writing Objective-C for a few years now, and decided to go back and learn the very basics to help me write even better code. I'm trying to learn all about instance variables, inheritance and class extensions. I've been reading up on all three, but there is one thing that boggles my mind. I have a simple app that contains 2 classes, Person, Male (inherits from Person), and of course Main (which imports the Male class, therefore being able to access the instance variables found in both Person and Male).
The code is simple, and for the sake of space I won't post all of it. Basically Main takes these variables and plays around with them. This is the part that is boggling my mind:
#interface Person : NSObject {
float heightInMeters;
int weightInKilos;
}
#property float heightInMeters;
#property int weightInKilos;
#end
When I delete the brackets and variable declarations, leaving it like this:
#interface Person : NSObject
#property float heightInMeters;
#property int weightInKilos;
#end
The code still inherits and executes just fine.
1. What is the point of even declaring them there in the first place if we can just create two properties?
2. why create two instance variables AND properties to correspond with them?
3. I know that we can declare the variables in the .m instead to keep them private to the class and everything that subclasses it. like this:
#implementation Person {
float heightInMeters;
int weightInKilos;
}
What is the difference here? I feel like I'm missing a lot of basics. Is there a simplistic way of putting this all in perspective?
When you declare a #property, the compiler will automatically synthesize the variable prefixed with an underscore, a getter method, and a setter method.
#interface MyClass ()
#property(strong, nonatomic) NSString *myString;
#end
In this example the compiler would syhtnesize the variable as _myString, the getter as
-(NSString *)myString
and the setter as
-(void)setMyString:(NSString *)string
The keywords after "#property" (strong, nonatomic) define the property's attributes. strong, the default, implies ownership, meaning that in this case MyClass instances will essentially be responsible for the retain/release of their respective myString objects. nonatomic means the variable is not guaranteed to always be a valid value in a multithreaded environment, for example if the getter is called at the same time as the setter.
Additionally, the compiler will treat dot syntax used to retrieve/set instance variables as calls to the appropriate getter/setter methods. Therefore, given an instance of MyClass
MyClass *exampleClass = [[MyClass alloc] init];
Both of the following are equivalent statements:
NSString *string1 = example.myString; // dot syntax
NSString *string1 = [example myString]; // explicit call to the getter method
For further reading, take a look at Apple's Programming with Objective-C Guide.
As for your specific questions:
1. What is the point of even declaring them there in the first place if we can just create two properties?
It's actually not a good idea to declare variables explicitly as public variables in your MyClass.h file (or in most other cases). Instead, declaring them as properties automatically creates a private variable (and accessor methods), making adhering to OOP best practices a little easier. So there is no point in declaring
// MyClass.h
#interface MyClass : NSObject {
NSString *myString // public variables not good
}
Also because of what I stated above regarding dot syntax, if you use self.myString internally in MyClass.m or instanceOfMyClass.myString externally, the public variable myString will never even be touched because the synthesized variable is named _myString.
2. Why create two instance variables AND properties to correspond with them?
See above--you don't need two instance variables, only one.
3. I know that we can declare the variables in the .m instead to keep them private to the class and everything that subclasses it. What is the difference here? I feel like I'm missing a lot of basics. Is there a simplistic way of putting this all in perspective?
If you declare your variables privately in the #implementation part of your .m file, the compiler won't be able to help you by synthesizing the getters and setters. Even as private methods, getters and setters can help reduce complexity in your code, for example checking for the validity of variable values. (Note: you can override accessor methods.)
// MyClass.m
#interface MyClass () // private interface
#property(nonatomic, strong) NSString *myString;
#end
#implementation MyClass {
// no more need for private variables!
// compiler will synthesize NSString *_myString and accessors
}
-(void)setMyString:(NSString *)string { // overwrite setter
// no empty strings allowed in our object (for the sake of example)
NSAssert([string length] > 0, #"String must not be empty");
// assign private instance variable in setter
_myString = string;
}
#end
This way, even when you subclass MyClass, the subclass will inherit the getter and setter methods that were synthesized for us by the compiler.

Can the ivar variable created automatically by properties accessible by the child class? [duplicate]

Since recent runtimes in iOS, we are able to define properties that will generate accessors for instance variables. From what I understand, it is not mandatory to declare the instance variable used since it will be automatically done for us.
For example, if I write:
#interface MyFirstClass
#property (readonly, nonatomic) int size;
#end
and in the .m
#implementation MyFirstClass
#synthesize size;
#end
Then an instance variable named "size" will be added for me and a method called "-(int)size" will be implemented.
The problem is that when I create a second class MySecondClass which is a subclass of MyFirstClass, it seems that I can't access the instance variable size within this subclass:
#interface MySecondClass : MyFirstClass
#end
#implementation MySecondClass
- (id)init {
if (self = [super init]) {
size = 10; // this yields and error
}
return self;
}
#end
Are the automatically created instance variables private? Is there a possibility to set them as protected so I can access them in subclasses?
I know there is the possibility to declare the instance variable myself, but I'm just wondering...
With a superclass like this it works: (Is it because it's expressly declared as protected?)
#interface MyFirstClass {
int size; // defined expressly and used as #protected
}
#property (readonly, nonatomic) int size;
#end
Thank you for your help!!
Nicolas.
Any instance variable not declared in the main interface is automatically private, and this cannot be overridden. If you try to use a scope modifier when defining instance variables in the implementation, you will get an error that the specification is inconsistent.
The reason for this is that there is usually only one class per implementation file, which means the compiler doesn't know about the instance variable when compiling other classes. If you have multiple classes in the same file, the compiler could know about it, but you still aren't allowed to override the scope. Possible reasons in this case could be for consistency, or just so the compiler doesn't have to look in so many places for instance variables.
Use:
self.size = 10;
That will map to setSize method.

Is there a link between an object named "a" and an object named "_a"?

I am new to iOS so take me slow. When i declare an object in my .h view controller named "_a" and i declare a property "a" and when i synthesize in the .m file
#synthesize a=_a;
must i use "a" or "_a" when i modify that object ? ( "a" is a UINavigationController in my case).
In another question, does my compiler automatically draw a connection from a object declared "ob" to a "_ob" declaration ?
Again, sorry for the poor explanation but this environment isn't quite something i am use to.
An object declared like this:
#interface Example : NSObject {
NSObject *_a;
}
#property (retain) NSObject *a;
#end
And implemented like this:
#import "Example.h"
#implementation Example
#synthesize a = _a;
#end
Makes an ivar named _a and two accessor methods in the Example object. The accessor methods have these signatures:
- (NSObject *)a;
- (void)setA:(NSObject *)theA;
Method a returns the object in the _a ivar. Method setA releases the object stored in _a (if not nil), assigns the parameter to _a, and sends the parameter an retain message.
These methods may also be access through dot notation:
Example *e = [[Example alloc] init];
// These two are equivalent.
e.a = anotherNSObject;
[e setA:anotherNSObject];
// These two are equivalent.
anotherNSObject = e.a;
anotherNSObject = [e a];
Accessing _a directly will circumvent the accessor methods, potentially causing problems such as memory leaks. For example if _a holds the only reference to an object and a new object reference is assigned to _a the old object will become a leaked object.
To directly answer your two questions:
You may use either a or _a. In most cases you'll be better off using _a when reading the value within methods of the object declaring a, and setA (or a in dot notation) when setting the value of _a. Objects that use Example objects should use the accessor methods (with or without dot notation).
The complier does not automatically make a connection between ob and _ob declarations. In this example the #synthesize a = _a; statement makes the connection with the optional = _a. The ivar may have any name. #synthesize a = george; would also be valid. Without the = _a part the compiler would make an ivar named a and two accessor methods.
One further note: You may omit the declaration of _a in the interface, which restricts the scope of the _a ivar to just the implementation of the Example object. Adding the optional = _a to the #synthesize statement will make as ivar of the same type as the property declared in the interface.
#synthesize tell to compiler to generate setter and getter methods for your property. You can use _a as ivar or self.a as property, there are no difference.
Also you can set your class variable from another class via this property
[myClassInstance setA:newA];
oldA = [myClassInstance a]; //oldA = myClassInstance.a

Difference between #interface declaration and #property declaration

I'm new to C, new to objective C. For an iPhone subclass, Im declaring variables I want to be visible to all methods in a class into the #interface class definition eg
#interface myclass : UIImageView {
int aVar;
}
and then I declare it again as
#property int aVar;
And then later I
#synthesize aVar;
Can you help me understand the purpose of three steps? Am I doing something unnecessary?
Thanks.
Here, you're declaring an instance variable named aVar:
#interface myclass : UIImageView {
int aVar;
}
You can now use this variable within your class:
aVar = 42;
NSLog(#"The Answer is %i.", aVar);
However, instance variables are private in Objective-C. What if you need other classes to be able to access and/or change aVar? Since methods are public in Objective-C, the answer is to write an accessor (getter) method that returns aVar and a mutator (setter) method that sets aVar:
// In header (.h) file
- (int)aVar;
- (void)setAVar:(int)newAVar;
// In implementation (.m) file
- (int)aVar {
return aVar;
}
- (void)setAVar:(int)newAVar {
if (aVar != newAVar) {
aVar = newAVar;
}
}
Now other classes can get and set aVar via:
[myclass aVar];
[myclass setAVar:24];
Writing these accessor and mutator methods can get quite tedious, so in Objective-C 2.0, Apple simplified it for us. We can now write:
// In header (.h) file
#property (nonatomic, assign) int aVar;
// In implementation (.m) file
#synthesize aVar;
...and the accessor/mutator methods will be automatically generated for us.
To sum up:
int aVar; declares an instance variable aVar
#property (nonatomic, assign) int aVar; declares the accessor and mutator methods for aVar
#synthesize aVar; implements the accessor and mutator methods for aVar
This declares an instance variable in your object:
#interface myclass : UIImageView {
int aVar;
}
Instance variables are private implementation details of your class.
If you want other objects to be able to read or set the value of the instance variable (ivar), you can declare it as a property:
#property int aVar;
This means that the compiler expects to see setter and getter accessor methods for the property.
When you use the #synthesize keyword, you are asking the compiler to automatically generate setter and getter accessor methods for you.
So, in this case the compiler will generate code similar to this when it encounters the #synthesize keyword:
- (int) aVar
{
return aVar;
}
- (void)setAVar:(int)someInt
{
aVar = someInt;
}
By default on the iPhone (and on the 32-bit runtime on the Mac), #synthesize requires an instance variable to be present in order to store the property's value. This ivar is usually named the same as the property, but doesn't have to be, for instance you could do this:
#interface myclass : UIImageView {
int aVar;
}
#property int someValue;
#synthesize someValue = aVar;
Neither #synthesize nor #property are actually required, you can create your own getter and setter methods, and as long as you create them using Key-Value Coding-compliant syntax, the property will still be usable.
The requirement for an ivar to be present as well as the #property declaration is due to the fragile base class limitation of the 32-bit Objective-C runtime on both the Mac and iPhone. With the 64-bit runtime on the Mac you don't need an ivar, #synthesize generates one for you.
Note that there are numerous keywords you can use with your #property declaration to control what sort of synthesized accessor code is created, such as readonly for a getter-only accessor, copy, atomic, nonatomic and so on. More information is in the Objective-C 2.0 Programming Language documentation.
Classes can have instance variables (ivars). These are in the first section, and are only visible to code in that class, not any outside code. I like to prefix them with an underscore to show their internal-ness. In low level terms, the ivars are added as an additional member to the struct that the class you are creating uses internally.
The second declaration, #property, is a declared property. It is not required (except when you are using #synthesize), but it helps other programmers (and the compiler!) know that you are dealing with a property, and not just two methods -setAVar and -aVar, which is the alternative way of doing this.
Thirdly, the #synthesize actually creates the methods to set and access the property from outside the class. You can replace this with your own setter and getter methods, but only do that if you need to, as the built-in ones have some features that you would otherwise have to code yourself. In fact, using the #synthesize aVar = _someVariable; syntax, you can have your property actually reference a differently named instance variable!
Short version:
The #property is just a hint to the compiler and other programmers that you are making a property and not just getter/setter methods. The instance variables are internal to the class, and otherwise cannot be normally accessed from outside it. The #synthesize just creates simple getters and setters for you, to go with your #property, but you can also just code those getters and setters yourself, like any other method.
Class A
#interface myclass : UIImageView {
int aVar;
}
If you declare like this then you can only use this variable within your class A.
But suppose in Class B
A *object=[A new];
object.aVar---->not available
For this you should **declare aVar as a property in Class A**
so class A should look like
Class A
#interface myclass : UIImageView {
int aVar;
}
#property int iVar;
and
.m file
#synthesize iVar;
So now you can use this iVar in another class Suppose B
Class B
#import "Class A.h"
enter code here
A *object=[A new];
object.aVar---->available
means
object.aVar=10;
#interface declares the instances variables of a class in obj-c. You need it to create an instance variable. However the variable is not visible outside the class by default (as the field is by default protected).
#property tells the compiler to specify a particular property accessor (get/set) method. However, you will need to use #synthesize to actually have the compiler generate the simple accessors automatically, otherwise you are expected to create them on your own.
I recently started learning iphone apps. As per my knowledge #property is used in .h file as a setter method and #synthesize in .m file as getter method. In Java we use setter and getter methods, same as Java, in Objective C we use #property and #synthesize.
Please forgive me If u think I mislead you.