2

I'm new to Objective C, and am using the Stanford CS193P course for the basics. In the first lecture, according to what I understood from it, anytime I declare a property in the header file, Objective C auto-generates the setter and getter for the property, where the getter name is the same as the property name. The professor also mentioned about the @synthesize keyword, which is used to set something as the instance variable name, like so @synthesize card = _card.

So now, any changes can be made to the property by using _card directly as well.

However, he mentions many times that all this happens behind this scenes and none of this appears to us in the implementation file.

If that's the case, then in the code below:

//
//  PlayingCard.h
//  CardGame
//
//  Created by Manish Giri on 9/19/15.
//  Copyright (c) 2015 Manish Giri. All rights reserved.
//

#import "Card.h"

@interface PlayingCard : Card

@property (nonatomic,strong) NSString *suit;    //one of club, heart, spade, diamond
@property (nonatomic) NSUInteger rank;  //numbers from 0 through 13

@end



//
//  PlayingCard.m
//  CardGame
//
//  Created by Manish Giri on 9/19/15.
//  Copyright (c) 2015 Manish Giri. All rights reserved.
//

#import "PlayingCard.h"

@implementation PlayingCard

//@synthesize suit = _suit;

//override the getter method "contents" to return the description- rank&suit of the playing card
-(NSString *) contents {

    //return [NSString stringWithFormat:@"%lu %@", (unsigned long)self.rank, self.suit];

    //if rank is 0 or not set, return ?
    NSArray *rankStrings = @[@"?", @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", @"12", @"13"];
    return [rankStrings[self.rank] stringByAppendingString:self.suit];
}

-(NSString *) suit {

    //return ? if suit is nil or not set
    return _suit?_suit:@"?";
}

-(void) setSuit:(NSString *)suit {
    //check the suit to be set is valid
    if([@[@"♥︎", @"♦︎", @"♠︎", @"♣︎"] containsObject:suit]) {
        _suit = suit;
    }
}

@end

Why do I get the error:

Use of undeclared identifier _suit. Did you mean suit?

After I got this error, I added the line @synthesize suit = _suit, and the error was fixed, but isn't this done automatically? If not, what's the difference?

The professor, most certainly, did not have the @synthesize line in his code (in the slide) while still using _suit.

1
  • 2
    Nicely asked question. Commented Sep 19, 2015 at 8:26

3 Answers 3

1

You have defined your own getter/setter and so have turned off this automatic generation of the instance variable. You will need to add your own instance variable:

@implementation PlayingCard () {
    NSString *_suit;
}
@end

@implementation PlayingCard
...
@end

I would also strongly suggest you use an enum for the suits as @"♥︎", @"♦︎", @"♠︎", @"♣︎" are presentation formats and are less useful to your code. For example:

// This should be in the header file
typedef enum {
    SUIT_NONE,
    SUIT_HEARTS,
    SUIT_DIAMONDS,
    SUIT_SPADES,
    SUIT_CLUBS
} Suit;

@implementation PlayingCard () {
    Suit _suit;
}
@end

It's now much easier and efficient to do:

if (_suit == SUIT_CLUBS) { ... }

than:

if ([_suit isEqualToString:@"♣︎"]) { ... }

Enums can also be used in switch statements and you will also find it easier for code using this class as well, for example:

if (cardsOnTable[i].suit == _cardsInHand[j].suit) {
    points++;
}
Sign up to request clarification or add additional context in comments.

Comments

0

It is done for you, unless you explicitly implement both the setter and getter methods yourself. I think you should also have seen a compile warning that this was happening on the property definition.

When you specify a property you're defining the thread and memory management, but if you then implement the accessor methods there is no guarantee you actually follow those rules. In this case you might actually be using some other memory all together so you need to tell the compiler what you want it to do.

Comments

0

All that magic is gone once you override a getter method. When you override it, you have to manually declare ivar backing the property or use @synthesis which essentially does the same. You can still define custom setter though and find that ivar is still there.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.