How to inherit object and initialize : Objective-C - objective-c

I created an object called Model that has some methods. I want to import Model into Mediator to use its methods there. But when I try to do this in Mediator.m I keep getting errors:
Initializer element is not a compile-time constant & No known class method for selector 'add'
I'm confused at to what these error are getting at. Researching them has not made things more clear.
Model.h
#interface Model : NSObject
#property (nonatomic) NSInteger tally;
-(int) add;
#end
Model.m
#import "Model.h"
#interface Model ()
#end
#implementation Model
- (instancetype)init
{
self = [super init];
if (self) {
self.tally = 0;
}
return self;
}
- (int)add {
self.tally = self.tally + 1;
return self.tally;
}
#end
Mediator.h
#interface MediatorController : NSObject
- (int)addOne;
#end
Mediator.m
#interface MediatorController ()
#end
#implementation MediatorController
Model *model = [[Model alloc] init]; <<<<<<< "Initializer element is not a compile-time constant"
- (int)addOne {
return [Model add]; <<<<<< "No known class method for selector 'add"
}
#end

First, you'll need a model property on your MediatorController
#interface MediatorController : NSObject
#property (strong, nonatomic) Model* model; //<-- Here
- (int)addOne;
- (int)subtractOne;
- (void)setValue:(int)value;
- (int)value;
#end
Then, you need an init method -- right now, you're trying to write your model = at the top level of the implementation, which doesn't work -- it needs to be inside a method.
Lastly, instead of calling add on Model (which is the class), call it on self.model, which is the instance of the class.
#implementation MediatorController
- (instancetype)init { //< -- Here
if (self = [super init]) {
self.model = [Model new];
}
return self;
}
- (int)addOne {
return [self.model add];
}
#end
You'll end up with a few compiler warnings because you haven't implemented the rest of the methods yet (subtractOne, setValue, etc), but this will get you started.

Related

Why am I getting the superclass and not the subclass in my method call?

I have this class, which is a port from a C# abstract class; this is the .h file:
#interface Schedule : NSObject {
}
#property (strong, nonatomic) NSDate *apptStartTime;
#property (strong, nonatomic) NSDate *apptEndTime;
#property (strong, nonatomic) NSString *key;
-(BOOL) occursOnDate: (NSDate *) timeOfAppointment;
#end
This is the .m file for Schedule:
#implementation Schedule {
}
#synthesize apptStartTime;
#synthesize apptEndTime;
#synthesize key;
/**
The OccursOnDate method is abstract and must be implemented by subclasses. When passed a date, the schedulers must determine if an appointment falls on that date. If one does, the method should return true. If not, the method returns false.
*/
-(BOOL) occursOnDate: (NSDate *) dateOfAppointment {
return YES:
}
Because it's a C# abstract class, it has to be overridden (or subclassed) which I have done here (this is the .h file):
#interface SingleSchedule : Schedule {
}
#property (strong,nonatomic) NSDate *apptDate;
-(BOOL) occursOnDate: (NSDate *)date;
#end
This is the .m file:
#implementation SingleSchedule {
}
#synthesize apptDate;
-(BOOL) occursOnDate: (NSDate *)date {
return (apptDate == date); // <--------- TODO where is apptDate set?
}
This is where I call the occursOnDate class, expecting to get the subcclass, but I get the superclass class instead:
-(void) addAppointmentsForDate:(NSDate *)checkDate scheduleSet: (NSMutableSet *)setOfSchedules appointmentSet:(NSMutableSet *)setOfAppts {
Schedule *sc = [[Schedule alloc]init];
Appointment *newAppt = [[Appointment alloc]init];
NSArray *scheduleArray = [setOfSchedules allObjects];
for(int i = 0; i < scheduleArray.count; i++) {
if([sc occursOnDate: checkDate]) { // <-------- method called is the superclass, not the override
newAppt = [self generateAppointment:checkDate andSchedule: scheduleArray [i]];
[setOfAppts addObject:newAppt];
}
}
}
What am I missing here to be able to get the subclass method and not the other? (I have looked at SO and Google but found nothing which would answer this question exactly).
The base class implementation is being called because sc is of type Schedule, not SingleSchedule. When you instantiate a class, the new object is aware of it's own implementation and it's base class chain, but the object is not aware of it's inherited classes.
Maybe what you want is:
SingleSchedule *sc = [[SingleSchedule alloc]init];

Objective-C : Calling a property of a class in another

I'm using Cocos2d and I can not access properties of an object from another one.
Here I just want to get the hitpoints of a ship form a scene. It fails and returns an error : uncaught exception 'NSInvalidArgumentException', reason: '-[CCSprite hitpoints]: unrecognized selector...
As hitpoints is declared in the interface of the class Ship I can't figure out why.
The only thing I understand is that it's a inhéritance issue.
Let's show some code :
Ship.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface Ship : CCSprite {
int hitpoints;
}
#property (nonatomic, assign) int hitpoints;
- (id)init;
#end
Then Ship.m
#import "Ship.h"
#implementation Ship
#synthesize hitpoints;
- (id)init
{
hitpoints = 3;
self = [CCSprite spriteWithImageNamed:#"ship.png"];
return self;
}
#end
In the Scene.m
#import "Ship.h"
#implementation Scene
{
Ship *_player;
}
- (id)init
{
_player = [[Ship alloc] init];
[self addChild:_player];
// ERROR HERE
NSLog(#"%s = %d", "_player hp", [_player hitpoints]);
}
Thank you.
I suspect the issue is with your init method; you shouldn't be accessing properties until the object is initialised and you should be calling [super initWith...] instead of the class creation method.
I would suggest the following changes:
Ship.h:
#interface Ship : CCSprite
#property (nonatomic, assign) int hitpoints;
#end
Ship.m:
#import "Ship.h"
#implementation Ship
#synthesize hitpoints;
- (id)init
{
self = [super initWithImageNamed:#"ship.png"];
if (self) {
self.hitpoints = 3;
}
return self;
}
#end
Always use object.property when referencing a property, even when object == self.
This:
- (id)init
Means "a method that returns any kind of object, which is called init".
This:
self = [CCSprite spriteWithImageNamed:#"ship.png"];
Means "create an instance of CCSprite". You then return that instance.
So _player ends up being an instance of CCSprite. CCSprite does not implement hitpoints so the exception is raised.
What are you actually trying to achieve? A subclass of CCSprite? trojanfoe has covered how to write a proper init for that. Things I think you need to know:
all classes look the same at runtime;
declaring the type of class pointers helps humans and the compiler to check your code but doesn't change the code generated;
some Objective-C patterns (probably most notably including class clusters) are built around init being able to return any kind of class — it's a useful feature, not a misfeature.

Getting an error on my (first ever) CardGameViewController

I'm getting the error incompatible pointer types assigning to Deck *__strong from PlayCards *
And i'm not sure why is that. Its in the first method implemented (deck):
#import "CardGameViewController.h"
#import "PlayingCards.h"
#interface CardGameViewController ()
#property (weak, nonatomic) IBOutlet UILabel *cardLabel;
#property (nonatomic) NSUInteger flipsCount;
#property (strong, nonatomic) Deck *deck;
#end
#implementation CardGameViewController
-(Deck *) deck {
if (!_deck) _deck = [[PlayingCards alloc] init];
return _deck;
}
-(void) setFlipsCount:(NSUInteger)flipsCount {
_flipsCount = flipsCount;
self.cardLabel.text = [NSString stringWithFormat:#"Flips:%d", self.flipsCount];
}
- (IBAction)flipCard:(UIButton *)sender {
sender.selected = !sender.isSelected;
self.flipsCount++;
}
#end
This is the header file(nothing going on here):
#import <UIKit/UIKit.h>
//#import "Card.h"
//#import "Deck.h"
//#import "PlayingCards.h"
#interface CardGameViewController : UIViewController
#end
And the PlayingCard class inheriting from Deck class..
this is the PlayingCards.m
#import "PlayingCards.h"
#implementation PlayingCards
#synthesize suit = _suit;
//modifying the contents getter so it will return array with the ranks and rank+suit
-(NSString *) contents {
NSArray *cardsRank = [PlayingCards rankStrings];
return [cardsRank[self.rank] stringByAppendingString:self.suit];
}
//creating a method to make sure we get validated suits
+(NSArray *) validSuit {
return #[#"♠",#"♣",#"♥",#"♦"];
}
//creating calss method to validate the rank
+(NSArray *) rankStrings {
return #[#"?",#"A",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"J",#"Q",#"K"];
}
//creating a new setter for suit to make sure we get the valitated suits, uding the validateSuit method
-(void) setSuit:(NSString *)suit {
if ([[PlayingCards validSuit] containsObject:suit]) {
_suit = suit;
}
}
//creating new getter for suit to make sure its not empty
-(NSString *) suit {
return _suit? _suit: #"?";
}
//creating a class method to make sure when user set the rank he will will
+(NSUInteger) maxRank {
return [self rankStrings].count - 1;
}
//creating a new setter to the renk to make sure the rank is validates
-(void) setRank:(NSUInteger)rank {
if (rank <= [PlayingCards maxRank]) {
_rank = rank;
}
}
#end
PlayingCards.h
#import "Card.h"
#import "Deck.h"
#interface PlayingCards : Card
#property (strong, nonatomic) NSString *suit;
#property (nonatomic) NSUInteger rank;
+(NSArray *) validSuit;
+(NSUInteger) maxRank;
#end
This line:
if (!_deck) _deck = [[PlayingCards alloc] init];
Should be:
if (!_deck) _deck = [[PlayingCardDeck alloc] init];
If the parent for Card is of class NSObject as you say, and given that PlayingCards inherits from Card, then you can't assign an instance of PlayingCards to a variable of type Deck*. That's what the compiler is telling you.
If you really need to do it, you have to write:
if (!_deck) _deck = (Deck*)[[PlayingCards alloc] init];
It would only be valid because in Objective-C the implementation is given at runtime and which method of which class is called is only decided at runtime when the message is dispatched. However, this pattern is very unusual and you better be certain that PlayingCards is implementing all the selectors that might be called on a Deck instance. A better way would be to use protocols.
You can define a protocol and then use:
id <myProtocol> deck = [[PlayingCards alloc] init];
Put in the protocol all the selectors you need.
Why can't you use this ?
PlayingCards* deck = [[PlayingCards alloc] init];

Why This Class <Not Responding>

Hi
i dont know why i call a function in "msg" class
it has no respond:(
this is the "msg" class:
msg.h :
#import <UIKit/UIKit.h>
#interface msg : NSObject {
}
-(void) Print;
#end
msg.m :
#import "msg.h"
#implementation msg
-(void) Print {
NSLog(#"Hello World");
}
#end
viewController.h :
#import <UIKit/UIKit.h>
#import "msg.h"
#class msg;
#interface ClassMod4ViewController : UIViewController {
msg *object;
}
#property (nonatomic,retain) msg *object;
#end
viewController.m :
#import "ClassMod4ViewController.h"
#implementation ClassMod4ViewController
#synthesize object;
- (void)viewDidLoad {
[object Print];
[super viewDidLoad];
}
Thanks
Was the object initialized in the designated initializer (usually initWithNibName:bundle: for UIViewController subclasses) prior to viewDidLoad being invoked?
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
// ...
object = [[Msg alloc] init];
// ...
return self;
}
If the object has not been initialized, then it's nil. Remember that it's okay to send nil objects messages in Objective-C (nothing will happen as a result).
have you tried:
- (void)viewDidLoad {
assert(object);
[object Print];
[super viewDidLoad];
}
?
if the assertion fails, then the pointer to object is 0 (or nil). you must create the object before you use it. this is typically performed in the initializer (in your case, of the class that contains the instance of object):
- (id)init {
self = [super init];
if (0 != self) {
object = [[msg alloc] init];
}
return self;
}
but sometimes you'll want to create the object later on.
if you are initializing it, then you may want to set breakpoints where the object is accessed in order to determine where the object is set to 0.

Help with a method that returns a value by running another object's method

I have a Class that runs the following method (a getter):
// the interface
#interface MyClass : NSObject{
NSNumber *myFloatValue;
}
- (double)myFloatValue;
- (void)setMyFloatValue:(float)floatInput;
#end
// the implementation
#implementation
- (MyClass *)init{
if (self = [super init]){
myFloatValue = [[NSNumber alloc] initWithFloat:3.14];
}
return self;
}
// I understand that NSNumbers are non-mutable objects and can't be
// used like variables.
// Hence I decided to make make the getter's implementation like this
- (double)myFloatValue{
return [myFloatValue floatValue];
}
- (void)setMyFloatValue:(float)floatInput{
if ([self myFloatValue] != floatInput){
[myFloatValue release];
myFloatValue = [[NSNumber alloc] initWithFloat:floatInput;
}
#end
When I mouse over the myFloatValue object during debugging, it does not contain a value. Instead it says: "out of scope".
I would like to be able to make this work without using #property, using something other than NSNumbers, or other major changes since I just want to understand the concepts first. Most importantly, I would like to know what mistake I've apparently made.
I can see a couple of mistakes:
The line #implementation should read #implementation MyClass
The function setMyFloatValue is missing a closing ] and } —it should read:
- (void)setMyFloatValue:(float)floatInput{
if ([self myFloatValue] != floatInput){
[myFloatValue release];
myFloatValue = [[NSNumber alloc] initWithFloat:floatInput];
}
}
I've just tested it in Xcode and it works for me with these changes.
Why not just set property in interface and synthesize accessors in implementation?
#interface MyClass : NSObject {
float *myFloat
}
#property (assign) float myFloat;
#end
#implementation MyClass
#synthesize myFloat;
#end