Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialMike Gilroy
7,411 PointsReadonly Attributes: 'randomPrediction' bug
After creating the custom CrystalBall class and following the video for what code to put where, I'm struggling to find the reason for the following error.
For the following piece of code I am getting an error that reads:
"No visible @interface for 'MGViewController' declares the selector 'randomPrediction'"
Here's the code with the error:
- (IBAction)buttonPressed {
self.predictionLabel.text = [self.crystalBall randomPrediction];
}
Also when typing out 'randomPrediction' above it does not suggest this as an option, which suggest something is not quite right in the first place.
If it helps this is all the code I have used for my app:
MGCrystalBall.h
#import <Foundation/Foundation.h>
@interface MGCrystalBall : NSObject
@property (nonatomic, strong) NSArray *predictions;
@property (nonatomic, strong) NSString *randomPrediction;
- (NSArray*) predictions;
- (NSString*) randomPrediction;
@end
MGCrsytalBall.m
#import "MGCrystalBall.h"
@implementation MGCrystalBall
- (NSArray *) predictions {
if (_predictions == nil){
_predictions = [[NSArray alloc] initWithObjects:
@"YES",
@"NO",
@"Maybe",
@"I can't be certain",
@"It's a definite",
@"It is doubtful",
@"My reply is no",
@"Unable to answer now",
nil];
}
return _predictions;
}
- (NSString*) randomPrediction {
int random = arc4random_uniform(self.predictions.count);
return [self.predictions objectAtIndex:random];
}
@end
MGViewController.h
#import <UIKit/UIKit.h>
@class MGCrystalBall;
@interface MGViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *predictionLabel;
@property (strong, nonatomic) MGViewController *crystalBall;
- (IBAction)buttonPressed;
@end
MGViewController.m
#import "MGViewController.h"
#import "MGCrystalBall.h"
@interface MGViewController ()
@end
@implementation MGViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.crystalBall = [[MGViewController alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (IBAction)buttonPressed {
self.predictionLabel.text = [self.crystalBall randomPrediction];
//above is the line of code where I am receiving the error
}
@end
Can anyone see where I have gone wrong here? Help would be much appreciated as I have gone back through the videos and can't see how my code differs to that in the videos.
Thanks in advance!
4 Answers
Stone Preston
42,016 Pointsoh. you also need to change a line in your header file as well. sorry I missed that the first time
see the error below. you need to have a MGCrystalBall property.
MGViewController.h
#import <UIKit/UIKit.h>
@class MGCrystalBall;
@interface MGViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *predictionLabel;
//this needs to be a crystal ball, not a MGViewController
@property (strong, nonatomic) MGViewController *crystalBall;
to fix it, just change it to a cyrstal ball object
MGViewController.h
#import <UIKit/UIKit.h>
@class MGCrystalBall;
@interface MGViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *predictionLabel;
//this needs to be a crystal ball, not a MGViewController
@property (strong, nonatomic) MGCrystalBall *crystalBall;
Stone Preston
42,016 PointsI think I found whats causing the issue. you are allocating your self.crystalBall property as an MGViewController object, not an MGCrystalBall object in your MGViewCOntroller.m file
MGViewController.m
#import "MGViewController.h"
#import "MGCrystalBall.h"
@interface MGViewController ()
@end
@implementation MGViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//this needs to be a crystal ball object, not a MGViewController
//see how you allocate it as an MGViewController object when it needs to be MGCrystalBall?
self.crystalBall = [[MGViewController alloc] init];
}
to fix it just change that line to
- (void)viewDidLoad
{
[super viewDidLoad];
//you need to allocate a MGCrystalBall object here.
self.crystalBall = [[MGCrystalBall alloc] init];
}
Mike Gilroy
7,411 PointsHi Stone, thanks for the quick response!
I've done what you've suggested though and this still doesn't get rid of the error, plus I'm now seeing a caution sign next to the new line of code reading "Incompatible pointer types assigning to 'MGViewController *' from 'MGCrystalBall *' "
Any idea what else might be wrong?
Here's the code after changing:
#import "MGViewController.h"
#import "MGCrystalBall.h"
@interface MGViewController ()
@end
@implementation MGViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.crystalBall = [[MGCrystalBall alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)buttonPressed {
self.predictionLabel.text = [self.crystalBall randomPrediction];
}
@end
Mike Gilroy
7,411 PointsThanks Stone, this fixed it! Think I must of just chosen the wrong one from the suggestions when typing out MG...
Cheers! :)
Stone Preston
42,016 Pointsyeah thats probably what happened. Glad you got it fixed