Amazon.com Widgets Program 7.1 - Error when I remove @synthesize
Welcome, Guest. Please login or register.
Did you miss your activation email?
May 25, 2013, 02:46:29 PM
Home Help Search chat Login Register   
News: Read this please.The Great Kangaroo Escape Looking for reviews of the 4th ed on Amazon!   Twitter:  @skochan
                     

+  Official Forum for Programming in Objective-C (the iPhone Programming Language) - Stephen Kochan
|-+  Programming in Objective-C, 4th edition
| |-+  Chapter 7
| | |-+  Program 7.1 - Error when I remove @synthesize
Pages: [1]   Go Down
Print
Author Topic: Program 7.1 - Error when I remove @synthesize  (Read 405 times)
mosley
Newbie
*
Posts: 7






« on: January 22, 2013, 08:43:27 PM »

When I comment out @synthesize I get a use of undeclared identifier error for numerator and denominator. I thought I could remove this with Xcode 4.5.

Code: (Objective-C)
@implementation Fraction

//@synthesize numerator, denominator;

-(void) print {
    NSLog(@"%i/%i", numerator, denominator);
}
-(double) convertToNum {
    if (denominator != 0)
        return (double) numerator / denominator;
    else
        return NAN;
}
@end
Logged
afterDark
Global Moderator
Full Member
*****
Posts: 126






« Reply #1 on: January 23, 2013, 06:36:22 AM »

Indeed will variables and accessors be automatically generated. But the naming of the variables and accessors follow strict rules. If you want those names to be different, do the @synthesize yourself.

From this https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html

Quote
Unless you specify otherwise, the synthesized instance variable has the same name as the property, but with an underscore prefix. For a property called firstName, for example, the synthesized instance variable will be called _firstName.

You might follow the suggestion from the book, doing @synthesize yourself, because (from same link)

Quote
If you use @synthesize without specifying an instance variable name, like this:

@synthesize firstName;

the instance variable will bear the same name as the property.

In this example, the instance variable will also be called firstName, without an underscore.

Logged

I am just an amateur with Objective-C, don't let the moderator label fool you. Working my way through the book slowly.
mosley
Newbie
*
Posts: 7






« Reply #2 on: January 23, 2013, 08:08:14 AM »

@afterDark

Thanks for your response, but I still do not get it. I only scanned the link from the Apple Developers site, and will thoroughly read it when I have more time, but you say:

Quote
If you want those names to be different, do the @synthesize yourself.

I thought I was naming my accessors and variables the same. But when I comment out the @synthesize statement I am asked if I want to rename the variables with an underscore.

Here is my interface code:
Code: (Objective-C)
@interface Fraction : NSObject

@property int numerator, denominator;
-(void) print;
-(double) convertToNum;

@end

Also, the setNumerator and setDenominator methods will no longer work. What do I use to get this data back from the class? I used the dot operator as explained in the next section, but I dont know if this is correct.

This is my main code:
Code: (Objective-C)
int main(int argc, const char * argv[])
{

    @autoreleasepool {
   
        Fraction *myFraction;
        myFraction = [Fraction alloc];
        myFraction = [myFraction init];
       
        myFraction.numerator = 1;
        myFraction.denominator = 3;
       
        [myFraction print];
       
    }
    return 0;
}
Logged
afterDark
Global Moderator
Full Member
*****
Posts: 126






« Reply #3 on: January 23, 2013, 08:32:52 AM »

Now I do not have so much time, but I'll write something quick, and maybe more thorough later.

First where you quote me, I have maybe been unclear. My apologies. What I meant was: the automatic process follows certain rules. If you want it different from those rules, make your own @synthesize. The book also does that, uses its own @synthesize.

The automatic process generates variables with names that are not the same as the property names. For a property called numerator, an instance variable will be created called _numerator (with the underscore _) . In my first answer, this is what is described in the first quote.

But, on the contrary, if you want the instance variable to have the same name as the property, you should use your own @synthesize. So if you have a property numerator, and you want the instance variable to also be called numerator, you should write:
Code: (Objective-C)
@synthesize numerator;
This is what the second quote in my first answer is about. Actually with @synthesize you can name the instance variables anything you like, for instance
Code: (Objective-C)
@synthesize numerator = greatVariableName;
or
Code: (Objective-C)
@synthesize numerator = _numerator;
etc. That last one, of course, is the same as the automatic way of doing things, when you leave out @synthesize.

your question about XCode suggesting to use an underscore _:
The errors in XCode actually being very helpful, suspected that you wanted to access a variable directly in your code (without accessor method). It detected there exists no variable numerator, but there is a variable _numerator, and suspecting a typo, suggests the change you describe.

your question about setNumerator and setDenominator not working:
I suppose you are talking about getting data into the class, not from the class? I do not know why your setters do not work. Could you maybe also post Fraction.m? Maybe the cause is there. And please tell a bit more what you mean with 'not working'.
Besides calling the setter methods with [myFraction setNumerator:3] you can also call them with  myFraction.numerator = 3 indeed.

Hope this helps!
« Last Edit: January 23, 2013, 08:40:57 AM by afterDark » Logged

I am just an amateur with Objective-C, don't let the moderator label fool you. Working my way through the book slowly.
mosley
Newbie
*
Posts: 7






« Reply #4 on: January 23, 2013, 07:17:42 PM »

THanks again afterDark! I think I understand it now. If I want to name the variables then use @synthesize. If not then they will be automatically named with an underscore.

My question about the setNumerator and setDenominator methods...

Before I changed the Fraction class by using the @property directive I used the setNumerator and setDenominator methods. But when I added the @property directive I removed those methods from the interface section. So now I can no longer use them in my main program, correct? So what am I supposed to use to set the numerator and denominator? I used the dot operator to do this. Is this the proper way? My Fraction.M code is in my first post.

Thanks again.



Logged
afterDark
Global Moderator
Full Member
*****
Posts: 126






« Reply #5 on: January 25, 2013, 05:40:18 AM »

First:
you do have #include "Fraction.h" in your main? Maybe you just did not include it when selecting the code for copying. And: sorry for this ridiculously long answer:

If you declare something to be a property, for instance
Code: (Objective-C)
@property int numerator, denominator
and you do not use @synthesize, you will have two instance variables called _numerator and _denominator, and the setters and getters for those variables, called setNumerator: and numerator for the first, and setDenominator: and denominator for the second.

You can just call these methods. Actually it is the preferred way to access that variable, instead of retrieving the variable directly.

So where you have in Fraction.m
Code: (Objective-C)
-(void) print {
    NSLog(@"%i/%i", _numerator, _denominator);
}
you can do
Code: (Objective-C)
-(void) print {
    NSLog(@"%i/%i", [self numerator], [self denominator]);
}

in main.m you can set the values of the instance variables by doing:
Code: (Objective-C)
[myfraction setNumerator:1];
[myfraction setDenominator:3];

It might be a good idea to stop reading here, try all that in your own code and make sure it works. Change it a little bit and see if the results of that are as you expect, until you feel you understand.

Now the dot notation, which is this: myfraction.numerator = 3;
The dot notation is another notation for [object message]. It is interpreted the same as if you would have written [myfraction setNumerator:3];
While using dot notation, the compiler tries to figure out wat method you mean. When you do
Code: (Objective-C)
myfraction.numerator = 3;
you probably want to set the value, so it replaces the dot notation internally with
Code: (Objective-C)
[myfraction setNumerator:3];
When you do
Code: (Objective-C)
x = myfraction.numerator;
you probably want to get the value, so it replaces that internally with
Code: (Objective-C)
x = [myfraction numerator];

So actually you were calling the setter method in your main already Smiley


Logged

I am just an amateur with Objective-C, don't let the moderator label fool you. Working my way through the book slowly.
mosley
Newbie
*
Posts: 7






« Reply #6 on: January 25, 2013, 12:30:44 PM »

Yes, I do have #include "Fraction.h" in my main, I neglected to copy that line.

I think i got it now (I started Ch7 over again). My confusion was when I do not use the @synthesize directive the instance variables must have the underscore. If I do use the @synthesize directive, i can call the instance variables whatever I like.

Another part of my confusion was when I use the @property directive in the interface section, I remove my setter methods (setNumerator: and setDenominator:) from my interface section, yet I still leave the setter methods in my main program, and they still set my instance variables. How does this work? Xcode does this automatically?

For example, suppose I had a class where I used @property int myVariable; to identify my property. Would this automatically set up a setter method called setMyVariable: to set the myVariable instance variable in my main program?
Logged
mosley
Newbie
*
Posts: 7






« Reply #7 on: January 25, 2013, 01:26:25 PM »

With regards to the second part of my previous post - This is from page 134 of the 5th Edition:

Quote
The following line tells the Objective-C compiler to generate a pair of getter and setter mothods for each of the two properties, numerator and denominator:

Code: (Objective-C)
@synthesize numerator, denominator;

In general, if you have a property called x, including the following line in your implementation section causes the compiler to automaticallty synthesize a getter method called x and a setter method called setX:.

Code: (Objective-C)
@synthesize x;

So when I use the @property and @synthesize directives the compiler automatically generates a setter method beginning with set, and the first letter of the property is capitalized.

I tested this in the following program:
Code: (Objective-C)
// Interface Section
#import <Foundation/Foundation.h>

@interface Fraction : NSObject

@property int myVariable;

-(void) print;

@end


// Implementation Section
#import "Temp.h"

@implementation Fraction

//@synthesize myVariable

-(void) print {
    NSLog(@"%i", _myVariable);
}

@end

// Main Program
#import <Foundation/Foundation.h>
#import "Temp.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        Temp *myTemp = [[Temp alloc] init];
       
        [myTemp setMyVariable:54];
        [myVariable print];
    }
    return 0;
}
Program Output: 54

Note that I commented out the @synthesize directive and used the underscore for my property.

Am I understanding this correctly?
Logged
afterDark
Global Moderator
Full Member
*****
Posts: 126






« Reply #8 on: January 25, 2013, 03:29:37 PM »

I think you understand it almost Smiley

like I said before, after @property, the compiler generates not only automatically the _instanceVariable, but also the setters and getters. With or without calling @synthesize!

In  the program in your last post, you do not use @synthesize, you did not declare the setter method yourself, yet you can still use a settermethod (you use setMyVariable: in line 37), because the compiler inserted one for you.

Logged

I am just an amateur with Objective-C, don't let the moderator label fool you. Working my way through the book slowly.
Pages: [1]   Go Up
Print
Jump to:  



Login with username, password and session length

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Entire forum contents (c) 2009 classroomM.com. All rights reserved.