You are confusing instance variables which are variables parts of an object structure, and properties which are really methods to set and get a value.
When you declare @property (strong, nonatomic) FirstClass *fromFirstClass;
you actually declare two methods - (FirstClass *)fromFirstClass
and - (void)setFromFirstClass:(FirstClass *)aFirstClass
.
When you use the dot syntax FirstClass *classA = self.fromFirstClass;
, you actually call a method, it is equivalent to FirstClass *classA = [self fromFirstClass];
. In the same way, if you write self.fromFirstClass = classB;
, you actually call: [self setFromFirstClass:classB];
.
If you use the name of an instance variable directly inside an object method, you access this variable.
Now, when you write @synthesize fromFirstClass;
in the modern runtime, you let the compiler create a instance variable with the same name fromFirstClass
and write the two methods - (FirstClass *)fromFirstClass
and - (void)setFromFirstClass:(FirstClass *)aFirstClass
that will get and set the instance variable.
If you write @synthesize fromFirstClass = _fromFirstClass;
, the same thing happens, except the name of the instance variable which is created has an underscore in front of it.
Finally, in the more recent versions of the compiler, if you don't write anything, the default behavior is to @synthesize fromFirstClass = _fromFirstClass
automatically for you.