Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

grandM

macrumors 68000
Original poster
Oct 14, 2013
1,551
309
Hi, I don't understand why I can't access self.cardButtons in the child class SetCardCardgameViewController. The parent is CardgameViewController.

CardgameViewController.h:
Code:
#import <UIKit/UIKit.h>
#import "Deck.h"

@interface CardgameViewController : UIViewController
- (void) updateUI;

//  protected
//  for subclasses

- (Deck *)createDeck;

// must be overriden in SetCardGameViewController as contents is not to be used for instance
- (NSAttributedString *)titleForCard: (Card *)card;
- (UIImage *)backgroundImageforCard: (Card *)card;

@end

CardgameViewController.m
Code:
#import "CardgameViewController.h"
//#import "PlayingCardDeck.h"
#import "CardMatchingGame.h"

@interface CardgameViewController ()

@property (strong, nonatomic) CardMatchingGame *game;
@property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons;
@property (weak, nonatomic) IBOutlet UILabel *scoreLabel;
@property (weak, nonatomic) IBOutlet UISegmentedControl *matchMode;
@property (weak, nonatomic) IBOutlet UILabel *status;
@property (weak, nonatomic) IBOutlet UISlider *historySlider;
@property (weak, nonatomic) IBOutlet UILabel *historyOverview;

@end

SetCardCardgameViewController.h
Code:
#import "CardgameViewController.h"

@interface SetCardCardgameViewController : CardgameViewController

@end

SetCardCardgameViewController.m
Code:
#import "SetCardCardgameViewController.h"
#import "SetCardDeck.h"
#import "SetCard.h"

@interface SetCardCardgameViewController ()

@end

@implementation SetCardCardgameViewController

- (void)updateUI
{
    for (UIButton *cardButton in self.cardButtons) {
        
    }

}

this last self.cardButtons isn't recognized. But cardButtons is a property of the parent class. Why isn't it recognized? I agree it's privately declared but as SetCardCardgameViewController is a child of CardgameViewController, I thought I could access all its properties and methods. Or am I mistaken?
 
Last edited:
It isn't recognized because the property isn't declared in the superclass. Instead, it's declared in a category of the superclass, and that declaration isn't in any header file you've shown, so it isn't importable by any other .m files.

Here's your code:
Code:
CardgameViewController.m
Code:
#import "CardgameViewController.h"
//#import "PlayingCardDeck.h"
#import "CardMatchingGame.h"

@interface CardgameViewController ()

@property (strong, nonatomic) CardMatchingGame *game;
@property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons;
@property (weak, nonatomic) IBOutlet UILabel *scoreLabel;
@property (weak, nonatomic) IBOutlet UISegmentedControl *matchMode;
@property (weak, nonatomic) IBOutlet UILabel *status;
@property (weak, nonatomic) IBOutlet UISlider *historySlider;
@property (weak, nonatomic) IBOutlet UILabel *historyOverview;

@end
First, notice what file it's in: CardgameViewController.m. That is, it's in the implementation of CardgameViewController. Since you're not importing a .m file (and you shouldn't), the properties declared in the category are unknown outside this specific .m file.

Next, look at the @interface in that file. What you've done is declared a nameless category on CardgameViewController. These properties (or methods, if there were any) would be visible to other classes if the category were declared in an importable .h file, but you didn't do that.


I'm guessing, but it looks to me like you don't understand the distinction between the interface of a class, and a category declared on a class. For example, you've got an empty category in SetCardCardgameViewController.m. What purpose does this serve? If you don't know, remove it.

Please explain exactly what book or tutorial you're learning from, and exactly what point you're at. If categories have been covered, then review that material. If you have no idea what a category is, then you're using things you haven't learned yet, and you're putting things (like properties) in the wrong place (like inside a non-public category).

Knowing what book or tutorial you're learning from will help us know what to suggest to correct the problem.
 
It isn't recognized because the property isn't declared in the superclass. Instead, it's declared in a category of the superclass, and that declaration isn't in any header file you've shown, so it isn't importable by any other .m files.

Here's your code:
Code:
CardgameViewController.m
Code:
#import "CardgameViewController.h"
//#import "PlayingCardDeck.h"
#import "CardMatchingGame.h"

@interface CardgameViewController ()

@property (strong, nonatomic) CardMatchingGame *game;
@property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons;
@property (weak, nonatomic) IBOutlet UILabel *scoreLabel;
@property (weak, nonatomic) IBOutlet UISegmentedControl *matchMode;
@property (weak, nonatomic) IBOutlet UILabel *status;
@property (weak, nonatomic) IBOutlet UISlider *historySlider;
@property (weak, nonatomic) IBOutlet UILabel *historyOverview;

@end
First, notice what file it's in: CardgameViewController.m. That is, it's in the implementation of CardgameViewController. Since you're not importing a .m file (and you shouldn't), the properties declared in the category are unknown outside this specific .m file.

Next, look at the @interface in that file. What you've done is declared a nameless category on CardgameViewController. These properties (or methods, if there were any) would be visible to other classes if the category were declared in an importable .h file, but you didn't do that.


I'm guessing, but it looks to me like you don't understand the distinction between the interface of a class, and a category declared on a class. For example, you've got an empty category in SetCardCardgameViewController.m. What purpose does this serve? If you don't know, remove it.

Please explain exactly what book or tutorial you're learning from, and exactly what point you're at. If categories have been covered, then review that material. If you have no idea what a category is, then you're using things you haven't learned yet, and you're putting things (like properties) in the wrong place (like inside a non-public category).

Knowing what book or tutorial you're learning from will help us know what to suggest to correct the problem.

Hi thanks for answering. A few months ago I went through a book from Kochan on objective-c. Much has gone forgotten though. Now I'm following the Stanford Itunes course. I'm at lesson 6, assignment 3.

I must admit the distinction between category and interface has gone vague. I thought what was declared in the .h file was accessible to all. What went inside the .m file was private. So if I put properties in the @interface in the .m file they couldn't be seen by other classes. I also thought that the properties in this .m file couldn't be gotten or set by another class. For instance another class wouldn't be able to perform the getter (or perform a setter) of status.

I did think I could access these properties if the class was a subclass of the class containing the properties (through inheritance), even if they were declared in the implementation. But apparently this isn't the case: if the subclass wants to access the properties of the superclass they must be declared in the .h file. Am I correct or am I making more mistakes?
 
I must admit the distinction between category and interface has gone vague. I thought what was declared in the .h file was accessible to all.

It is.

The problem is that the properties aren't in a .h file. If they were, and if the class that wanted to use them then imported the .h file, then the properties would be available. Since that isn't what you did, then you don't get that result.

What went inside the .m file was private. So if I put properties in the @interface in the .m file they couldn't be seen by other classes.
They aren't directly visible, but that's not the same thing as @private. And Objective-C doesn't allow @private on methods (or properties, IIRC), which means they're @public.

Since they're @public, that means any class that can either get a declaration or use reflection will be able to see the properties. You didn't do either of those, so the properties don't exist as far as your posted code is concerned.


I also thought that the properties in this .m file couldn't be gotten or set by another class. For instance another class wouldn't be able to perform the getter (or perform a setter) of status.
That's a side-effect of declaring the interface somewhere other than a .h file. It has no effect on @private vs. @public.

If the properties were in a header file, and another class imports that header, then the properties are accessible.


I did think I could access these properties if the class was a subclass of the class containing the properties (through inheritance), even if they were declared in the implementation. But apparently this isn't the case: if the subclass wants to access the properties of the superclass they must be declared in the .h file.
That's correct.

I think you should review the fundamentals of properties, visibility (@private, @public, etc.), and what a category actually is.

Right now, you're making fundamental errors because your recollection is faulty. Brush up the fundamentals first.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.